En el tema anterior hemos visto como se estructura de carpetas del proyecto. En este tema vamos a automatizar todos los procesos de la estructura de carpetas . Automatizar tareas es fundamental ya que se minimizan los errores que se cometen. Por otro lado el despliegue puede llegar a hacerse decenas de veces al día, por lo que obviamente debe estar automatizado.
Podemos pensar que instalar (desplegar) decenas de veces al día una aplicación es un poco exagerado pero en sitios web como Amazon ésto si que tiene sentido. Si en la aplicación de amazón hay un error que suele afectar al 0,1% de sus ventas. ¿Cuanto dinero pierden diariamente por tener ese error? Y en este tipo de aplicaciones se suelen estar constantemente realizando cambios y corrección de error , así que ¿porque no desplegarla en cuanto está corregido un error o añadida la nueva funcionalidad? Esto en la literatura informática se llama Continuous delivery
Para crear un proyecto de Spring Boot usar https://start.spring.io/
mvn clean install
java -jar miapp.jar
Vamos ahora a ver como podemos automatizar cosas en un proyecto Java con maven.
Para realizar tareas definidas en maven debemos usar pluings que hacen esas tareas.
Vamos a ver 2 plugins:
Para usar cada plugin hay que añadirlos al pom.xml dentro del tag:
<plugins> </plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>build-cliente</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>NOMBRE_DEL_EJECUTABLE_A_EJECUTAR</executable>
<workingDirectory>${project.basedir}</workingDirectory>
<arguments>
<argument>ARGUMENTO_1</argument>
<argument>ARGUMENTO_n</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.davidmoten</groupId>
<artifactId>plantuml-maven-plugin</artifactId>
<version>0.2.14</version>
<executions>
<execution>
<id>generate-diagrams</id>
<phase>generate-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<directory>${basedir}/src</directory>
<includes>
<include>**/*.puml</include>
</includes>
</sources>
<outputDirectory>${basedir}/src</outputDirectory>
<formats>
<format>png</format>
</formats>
<preserveDirectoryStructure>true</preserveDirectoryStructure>
<generateMarkdownIndex>false</generateMarkdownIndex>
</configuration>
</plugin>
Más información:
Para generar un proyecto en Angular se usa ng build:
ng build
Que genera una carpeta dist con el código compilado del proyecto.
Una vez compilado el proyecto necesitamos un servidor web, ese servidor HTTP puede ser:
Nosotros vamos a usar un script de NodeJS
Para ello vamos a crear un proyecto Node:
npm init npm install express
Crear el fichero index.js:
#!/usr/bin/env node
const express = require('express')
const path = require('path')
const app = express()
const port = 8080
const indexFolder = 'browser'
const distPath = path.join(__dirname, indexFolder)
app.use('/', express.static(distPath))
app.use((req, res, next) => {
const indexPath = path.join(distPath, 'index.html');
res.sendFile(indexPath);
});
app.listen(port, (err) => {
console.log(`server is listening on ${port}`)
console.log(`serving from ${distPath}`)
})
Ahora copiaremos la carpeta browser que creó Angular dentro de dist y la copiaremos en la raiz de nuestro proyecto Node.
Por último ejecutaremos la aplicación con
node ./index.js
Al igual que existe en java mvn en aplicaciones de NodeJS podemos usar npm run que ejecutará nuestros scripts.
En los siguientes artículos se explican los scripts npm:
Veamos ahora un ejemplo de Script de transformar SASS a CSS.
"scripts": {
"compile-scss": "sass ./scss/main.scss ./css/main.css"
}
npm run compile-scss
¿Que hemos ganado con ésto? Que ahora todas las "tareas" que tenemos que hacer en el proyecto se pueden ver en el package.json y siempre se ejecutarán como "npm run nombre-tarea"
Si vemos el package.json en un proyecto de Angular:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
}
ng serve se podría ejecutar
npm run start
ng build se podría ejecutar
npm run build
¿Que ganaríamos con eso? Que si siempre usamos por ejemplo npm run build podríamos modificar el package.json y en el proceso de build añadir más cosas:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build && miscript.sh",
"watch": "ng build --watch --configuration development",
"test": "ng test"
}
En ese caso en la linea 4 hacemos que además de crear en build se ejecute nuestro script miscript.sh.
O cosas como:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"build:production": "ng build --configuration production--define SOME_NUMBER=5 --define "ANOTHER='these will overwrite existing'"",
"watch": "ng build --watch --configuration development",
"test": "ng test"
}
En este caso al ejecutar:
npm run build:production
no tenemos que preocuparnos se saber que opciones hay que pasar a ng build
npm run