<div class="page"> <div class="cover text-center"> <img class="mx-auto" src=/itb/images/logo_mislata.png alt="logo"> # CI/CD - GitHub Actions <div class="text-end fit-content ms-auto my-3 mt-auto pt-3"> <p><strong>Autor:</strong> Joan Puigcerver Ibáñez</p> <p><strong>Correu electrònic:</strong> j.puigcerveribanez@edu.gva.es</p> <p><strong>Curs:</strong> 2024/2025</p> </div> <div> <p class="fw-bold mb-0">Llicència: BY-NC-SA</p> <p class="d-none d-md-block">(Reconeixement - No Comercial - Compartir Igual)</p> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ca" target="_blank"> <img class="mx-auto" src="/itb/images/license.png" alt="Licence"/> </a> </div><!--license--> </div><!--cover--> </div><!--page--> {:toc} ## Introducció En enginyeria del software, __CI/CD__ es coneix com a la combinació de les pràctiques d'__integració contínua (_continuous integration_ o CI)__ i de __distribució contínua (_continuous delivery_ o CD)__. - [CI/CD - Wikipedia](https://en.wikipedia.org/wiki/Continuous_integration) La __integració contínua__ consisteix a _integrar_ els canvis en desenvolupament a la branca _main_ d'una manera freqüent. - [Continuous integration - Wikipedia](https://en.wikipedia.org/wiki/Continuous_integration) La __distribució contínua__ consisteix a proporcionar una versió del software en períodes curts de temps, comprovant que el software pot ser posat en producció en qualsevol moment utilitzant una __canonada o _pipeline___ que s'encarrega de desplegar el software automàticament sense interacció humana. - [Continuous delivery - Wikipedia](https://en.wikipedia.org/wiki/Continuous_delivery) ## Configurar Maven __Maven__ és el software de gestió de projectes que utilitzem en el nostre projecte d'IntelliJ. Fins ara l'hem utilitzat per instal·lar llibreries i dependències del projecte. Anem a configurar-lo per poder executar els tests. En el fitxer __pom.xml__, hem d'afegir el següent contingut: - __Plugin__ `maven-surefire-plugin`: Aquest plugin ve inclòs per defecte en la configuració de Maven que realitza IntelliJ. No obstant, com estem utilitzant __JUnit5__, hem d'actualitzar el plugin a la versió 2.22.0. ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- JUnit 5 requires Surefire version 2.22.0 or higher --> <version>2.22.0</version> </plugin> </plugins> </build> ``` - __Dependència__ `junit-jupiter-engine`: Dependència de __JUnit5__ que necessitem. ```xml <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> ``` ### Exemple pom.xml ```xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>PuigcerverJoan-DAW1-ED-solutions</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- JUnit 5 requires Surefire version 2.22.0 or higher --> <version>2.22.0</version> </plugin> </plugins> </build> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>5.2.0</version> <scope>test</scope> </dependency> </dependencies> </project> ``` Una vegada actualitzat el __pom.xml__, sols cal actualitzar el projecte amb __Maven > Reload Project__. __Maven__ proporciona diferents accions, com compilar, empaquetar o provar el codi. En la finestra __Maven__ (barra dreta d'IntelliJ) podeu seleccionar les diferents accions (_Goals_) a exectuar. En aquest cas, volem utilitzar el _goal_ ___verify___, que compila i llança els tests del nostre projecte. ## GitHub Actions Com hem exposat abans, comprovar el funcionament del software d'una manera freqüent i __automàtica__ és una part de la __distribució contínua (CD)__. En aquest apartat s'explicarà com podem configurar el nostre repositori per llançar els tests automàticament mitjançant __GitHub Actions__. __GitHub Actions__ és una característica que ens ofereix GitHub, que permet automatitzar accions en certs events del repositori. _Per exemple, la publicació de una web estàtica mitjançant GitHub Pages es realitza mitjançant Actions_. Podeu accedir a les accions del vostre repositori en la pestanya __Actions__. En aquesta pàgina, podeu consultar les accions creades o configurar una nova acció. ![GitHub Action Tab](/itb/DAM-ED/UD8/img/actions/actions.png){.center} ### New Workflow Anem a crear una nova acció mitjançant el botó __New Workflow__, i anem a seleccionar la plantilla __Java With Maven__. Això ens obrira un editor amb el següent contingut: ```yaml name: Java CI with Maven on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v3 with: java-version: '11' distribution: 'temurin' cache: maven - name: Build with Maven run: mvn -B package --file pom.xml ``` ### Adaptar la plantilla Anem a desxifrar el seu contingut. Primer que res, especifiquem el nom del workflow amb l'etiqueta `name`. Anem a modificar el nom. ```yaml name: Test Java with Maven ``` La següent etiqueta és `on`, que especifica en quines circustàncies o events s'executarà aquesta acció. En aquest cas, s'executarà al fer un `push` o crear una `pull_request` a la branca `main`. També podem afegir `workflow_dispatch:` per poder llançar l'acció manualment. ```yaml on: push: branches: [ "main" ] pull_request: branches: [ "main" ] workflow_dispatch: ``` L'última etiqueta de l'àrrel és `jobs`, que especifica quines tasques ha de dur a terme l'acció. - La etiqueta `build` és el nom de la primera tasca, que la podem modificar a `test`. - L'etiqueta `runs-on` especifica quin entorn s'ha de configurar en el contenedor per executar les tasques. - L'etiqueta `steps` conté una llista amb els passos que s'han de seguir per completar aquesta tasca. ```yaml jobs: test: # Abans era build: runs-on: ubuntu-latest steps: - ... - ... ``` En aquest cas, s'executen els següents passos: 1. Es còpia el contingut del repositori al contenidor on s'executarà la tasca. - `uses` indica que utilitza una acció predefinida. En aques cas s'utilitza l'acció [actions/checkout@v4](https://github.com/actions/checkout) ```yaml - uses: actions/checkout@v4 ``` 2. Es configura la versió de Java que s'utilitzarà. En aquest cas, utilitzarem la versió 17 que hem especificat en el __pom.xml__. - `name` indica el nom de aquest pas. - `uses` indica que utilitza una acció predefinida. En aques cas s'utilitza l'acció [actions/setup-java@v3](https://github.com/actions/setup-java) - `with` serveix per establir el valor de les variables d'alguna acció predefinida. ```yaml - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' cache: maven ``` - __pom.xml__: ```xml <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> ``` 3. Per últim, compilem i llançem els tests mitjançant el _goal_ `verify` de __Maven__. - `run` serveix per establir quina comanda es vol executar en el contenedor. ```yaml - name: Verify with Maven run: mvn --batch-mode --update-snapshots verify ``` 4. Hem eliminat l'últim pas opcional de la plantilla. ### Workflow final El fitxer del workflow quedaria d'aquesta manera: ```yaml name: Test Java with Maven on: workflow_dispatch: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' cache: maven - name: Verify with Maven run: mvn --batch-mode --update-snapshots verify ``` Una vegada configurat, podem incloure l'acció realitzant un _commit_. Aquest fitxer es guardarà en la carpeta dedicada a les accions `.github/workflows`. ## Execució ### Workflow-dispatch Des de la pàgina __Actions__, podem navegar a l'acció "Test Java with Maven" i llançar-la manualment, gràcies a que hem establert `workflow_dispatch` en la configuració de l'acció. ![GitHub Action Workflow Dispatch](/itb/DAM-ED/UD8/img/actions/workflow_dispatch.png){.center} ### Push a `main` Si realitzem un `push` a la branca `main`, podem observar com s'executa l'acció. Una vegada realizada, veurem un tick verd si s'ha executat correctament o una creu roja si ha fallat. ![GitHub Action Push](/itb/DAM-ED/UD8/img/actions/actions_push.png){.center} ### Pull request a `main` El mateix passa quan creem una __Pull Request__. En aquest cas, el resultat de les comprovacions apareix en la pàgina des d'on es pot aprovar o rebutjar els canvis. D'aquesta manera és fàcil identificar si els tests no passen i podem decidir si volem o no incloure els canvis proposats. ![GitHub Action Push](/itb/DAM-ED/UD8/img/actions/actions_pullrequest.png){.center} ## Bibliografia - https://stackoverflow.com/questions/8180315/output-failed-test-details-to-stdout-using-maven-surefire