Zum Inhalt

GitHub Actions – Caching, Matrix Builds, Secrets und Artefakte

Berücksichtigt man einige Best Practices, so lassen sich GitHub Actions Workflows deutlich bezüglich Performance, Sicherheit und Wartbarkeit optimieren.


Vier Aspekte zur Optimierung

Caching & Performance

Ziel:
Builds schneller machen und Ressourcen sparen, indem wiederkehrende Daten (zBsp. Dependencies) zwischengespeichert werden.

Anwendung:

- name: Cache Maven repository
  uses: actions/cache@v4
  with:
    path: ~/.m2/repository
    key: maven-${{ hashFiles('**/pom.xml') }}

Matrix Builds / Parallelisierung

Ziel:
Das Projekt gleichzeitig mit unterschiedlichen Versionen (z. B. Java 17 und 21) oder Umgebungen testen.

Anwendung:

strategy:
  matrix:
    java-version: [ '17', '21' ]
GitHub Actions führt für jede Version automatisch einen Job parallel aus.

Secrets & sensible Daten

Ziel:
Passwörter, Tokens und API-Keys sicher speichern, statt sie im Code oder Workflow offenzulegen.

Anwendung: 1. In GitHub:
→ Settings → Secrets → Actions → New repository secret → z. B. MY_SECRET 2. Im Workflow:

env:
  MY_SECRET: ${{ secrets.MY_SECRET }}

Artefakte & Ergebnisse speichern

Ziel:
Build-Ergebnisse (z. B. JAR, Testreports) nach einem Lauf sichern und herunterladen können.

Anwendung:

- name: Upload JAR
  uses: actions/upload-artifact@v4
  with:
    name: app-jar
    path: target/demo-1.0-SNAPSHOT.jar

Projektgrundlage

Struktur:

demo-ci-project/
  .gitignore
  pom.xml
  src/
    main/java/com/example/App.java
    test/java/com/example/AppTest.java
  .github/workflows/initial_ci.yml

.gitignore

.DS_Store
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>demo-ci-project</artifactId>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.10.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

App.java

package com.example;

public class App {
    public static String greet(String name) {
        return "Hello " + name;
    }

    public static void main(String[] args) {
        System.out.println(greet("World"));
    }
}

AppTest.java

package com.example;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class AppTest {

    @Test
    void greetShouldIncludeName() {
        assertEquals("Hello World", App.greet("World"));
    }
}

Ausgangs-Workflow (ohne Best-Practices)

.github/workflows/ci.yml

name: Initial CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Java
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '17'

      - name: Build and test with Maven
        run: mvn -B clean verify

Aufgaben

Aufgabe 1: Projekt einrichten & Workflow testen

  1. Neues GitHub-Repository demo-ci-project erstellen.
  2. Projektstruktur und Dateien übernehmen.
  3. Workflow .github/workflows/ci.yml anlegen.
  4. Änderungen committen und pushen.
  5. Im Tab Actions prüfen, ob der Workflow automatisch ausgeführt wird.

Aufgabe 2: Caching & Performance verbessern

Ziel: Build beschleunigen.

  1. Ergänze den Workflow mit einem Cache für das Maven-Repository (~/.m2/repository).
  2. Verwende den Hash der pom.xml als Cache-Key.
  3. Vergleiche die Laufzeit des ersten und zweiten Builds.

Hinweis:

- name: Cache Maven repository
  uses: actions/cache@v4
  with:
    path: ~/.m2/repository
    key: maven-${{ hashFiles('**/pom.xml') }}

Aufgabe 3: Matrix Builds / Parallelisierung

Ziel: Projekt gleichzeitig mit Java 17 und Java 21 testen.

  1. Füge eine Strategy mit einer Matrix unter build-and-test in den Job ein: yaml build-and-test: runs-on: ubuntu-latest strategy: matrix: java-version: [ '17', '21' ]
  2. Optimiere den Cache-Step, damit für jede Java-Version ein eigener Cache verwendet wird:

       - name: Cache Maven repository
         uses: actions/cache@v4
         with:
           path: ~/.m2/repository
           key: maven-${{ runner.os }}-${{ matrix.java-version }}-${{ hashFiles('**/pom.xml') }}
           restore-keys: |
             maven-${{ runner.os }}-${{ matrix.java-version }}-
             maven-${{ runner.os }}-   
    
  3. Verwende matrix.java-version in setup-java.

        - name: Set up Java
          uses: actions/setup-java@v4
          with:
            distribution: temurin
            java-version: ${{ matrix.java-version }}
    
  4. Beobachte in GitHub Actions, dass zwei parallele Builds gestartet werden.

Aufgabe 4: Secrets & sensible Daten

Ziel: Einen geheimen Token sicher verwenden.

  1. Im Repository unter Settings → Secrets → Actions ein Secret APP_SECRET_TOKEN erstellen.

  2. Eine neue Klasse SecretUser.java hinzufügen:

    package com.example;
    
    public class SecretUser {
        public static boolean hasSecret() {
            String secret = System.getenv("APP_SECRET_TOKEN");
            return secret != null && !secret.isBlank();
        }
    }
    
  3. Einen Test schreiben, der prüft, dass hasSecret() true ist.

  4. Im Workflow:

    env:
      APP_SECRET_TOKEN: ${{ secrets.APP_SECRET_TOKEN }}
    

Aufgabe 5: Artefakte & Ergebnisse speichern

Ziel: Testreports und JAR-Datei sichern.

  1. Ergänze am Ende des Jobs zwei Upload-Schritte:

    - name: Upload JAR
      uses: actions/upload-artifact@v4
      with:
        name: app-jar-${{ matrix.java-version }}
        path: target/demo-ci-project-1.0-SNAPSHOT.jar
    
    - name: Upload test reports
      uses: actions/upload-artifact@v4
      with:
        name: test-reports-${{ matrix.java-version }}
        path: target/surefire-reports/
    
  2. Workflow ausführen und Artefakte im Actions-Tab herunterladen.


Zusammenfassung

Die Kombination dieser vier Techniken ist ein solider Einstieg in professionelle CI/CD-Pipelines.