Skip to content

Practice 2b ‐ Advanced Gradle CI CD

Ármin Zavada edited this page Sep 19, 2024 · 5 revisions

Practice 2b - Advanced Gradle CI/CD

Tasks

Task 0 - Preparations

Pull practice 2b materials - state of practice 2a end.

git remote add ase-labs https://github.com/ftsrg-edu/ase-labs.git
git fetch ase-labs
git switch practice-2b
git push -u origin

Task 1 - Split single-module project into multi-module project.

  1. Define and create subprojects.
    • lib - containing lib package main and test code.
    • logic - containing logic package main and test code, depends on lib.
    • similarity - containing similarity package main and test code, depends on logic and lib.
    • diversity - containing diversity package main and test code, depends on logic and lib.
  2. Create the build.gradle.kts build description script in each subproject.
  3. Include subprojects in settings.gradle.kts.
    include(
        "lib",
        "logic",
        "similarity",
        "diversity",
    )
  4. CHECK: ./gradlew build should function as before.
  5. Design dependency - Implementation vs. API.
    • Add java-library plugin.
      plugins { 
          `java-library`
      }
    • Add lib as API dependency to logic.
      dependencies {
          api(project(":lib"))
      }
    • Remove implementation(project(":lib")) from similarity and diversity.
  6. CHECK: ./gradlew build should function as before.
  7. Store subproject artifacts in GitHub Action pipeline.
    - name: Upload Artifacts
      uses: actions/upload-artifact@v4
      with:
        path: |
          **/build/distributions/*
          **/build/reports/*
  8. Commit and push added files.
  9. CHECK: GitHub Actions should work as before and should zip all subproject artifacts.

Task 2 - Reduce build configuration redundancy

  1. Extract shared build logic.

    • Create buildSrc directory.
    • Add settings.gradle.kts file (empty).
    • Add build.gradle.kts file.
      plugins {
          `kotlin-dsl`
      }
      
      repositories {
          mavenCentral()
      }
    • Create src/main/kotlin source directory inside buildSrc
    • Create java.gradle.kts convention plugin in src/main/kotlin.
      package hu.bme.mit.ase.shingler.gradle
      
      plugins {
          java
          jacoco
          `java-library`
      }
      
      java.toolchain {
          languageVersion.set(JavaLanguageVersion.of(21))
      }
      
      repositories {
          mavenCentral()
      }
      
      tasks {
          test {
              useJUnitPlatform()
              testLogging.showStandardStreams = true
              finalizedBy(jacocoTestReport)
          }
      
          jacocoTestReport {
              inputs.files(test.get().outputs)
          }
      }
    • Create application.gradle.kts convention plugin in src/main/kotlin.
      package hu.bme.mit.ase.shingler.gradle
      
      import org.gradle.kotlin.dsl.application
      
      plugins {
          id("hu.bme.mit.ase.shingler.gradle.java")
          application
      }
    • Replace build logic in subprojects with convention plugins.
    • CHECK: ./gradlew build functions as before.
  2. Extract dependency definitions into the version catalog.

    • Add dependency definitions to the version catalog.
      [versions]
      picoCli = "4.7.6"
      slf4j = "1.7.25"
      log4j = "2.23.1"
      logback = "1.5.8"
      jUnit = "5.10.0"
      
      [libraries]
      picocli = { group = "info.picocli", name = "picocli", version.ref = "picoCli" }
      slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" }
      slf4j-log4j-impl = { group = "org.apache.logging.log4j", name = "log4j-slf4j-impl", version.ref = "log4j" }
      slf4j-logback-impl = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" }
      junit-jupiter-core = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "jUnit" }
      junit-jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "jUnit" }
    • Replace dependencies with version catalog references: e.g., implementation("org.slf4j:slf4j-api:$slf4jVersion") becomes implementation(libs.slf4j.api).
    • CHECK: ./gradlew build functions as before.
  3. Commit and push added files.

  4. CHECK: GitHub Actions CI should pass.

Task 3 - Advanced GitHub Actions configuration

  1. Create matrix build configuration.
    jobs:
      build:
        name: Build
        strategy:
          matrix:
            os:
              - ubuntu-latest
              - ubuntu-20.04
              - windows-latest
              - macos-13
        runs-on: ${{ matrix.os }}
        steps:
          # ...
          - name: Upload Artifacts
            if: ${{ matrix.os == 'ubuntu-latest' }} # add conditional execution
  2. Add end-to-end integration test job.
      e2e-integration:
        name: End-to-end Integration test
        needs: build
        runs-on: ubuntu-latest
        steps:
          - name: Set up JDK 21
            uses: actions/setup-java@v4
            with:
              java-version: 21
              distribution: adopt
          - name: Checkout code
            uses: actions/checkout@v4
          - name: Download Distribution
            uses: actions/download-artifact@v4
            with:
              name: artifact
              path: artifact
          - name: Extract Distribution
            uses: ihiroky/extract-action@v1
            with:
              file_path: artifact/similarity/build/distributions/similarity.tar
              extract_dir: dist
          - name: Test Similarity
            run: |
              dist/similarity/bin/similarity muse1.txt muse2.txt 3 > e2e-output.txt
              grep -xq "Similarity:0.9000325774286236" e2e-output.txt
          - name: Upload Output
            uses: actions/upload-artifact@v4
            with:
              name: standard-output
              path: e2e-output.txt
  3. Commit and push added files.
  4. CHECK: GitHub Actions should run a build on all platforms, and execute the e2e testing successfully!

The final state of the practice can be looked at for reference: https://github.com/ftsrg-edu/ase-labs/tree/practice-2b-end