diff --git a/.gitea/workflows/base-build.yml b/.gitea/workflows/base-build.yml index e4f38b0..d61c9ae 100644 --- a/.gitea/workflows/base-build.yml +++ b/.gitea/workflows/base-build.yml @@ -20,68 +20,73 @@ env: CACHE_DIR: .cache jobs: - check-base-images-and-build: + check-for-changes: runs-on: doc-docker-build + outputs: + should_build_alpine: ${{ steps.check.outputs.should_build_alpine }} + should_build_debian: ${{ steps.check.outputs.should_build_debian }} steps: - name: Checkout code uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Gitea Registry - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ env.IMAGE_REGISTRY }} -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin - - - name: Get alpine:latest digest - id: alpine_digest + - name: Pull latest base images run: | - docker pull docker.io/library/alpine:latest - DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' alpine:latest || echo "unknown") - echo "digest=$DIGEST" >> $GITHUB_OUTPUT + docker pull alpine:latest + docker pull gitea.fithwum.tech/${{ secrets.GIT_USERNAME }}/debian-base:bookworm - - name: Get debian-base:bookworm digest - id: debian_digest + - name: Get base image digests + id: get_digest run: | - IMAGE="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_ORG }}/${{ env.IMAGE_REPO_DEBIAN }}:${{ env.IMAGE_TAG_DEBIAN }}" - docker pull "$IMAGE" - DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE" || echo "unknown") - echo "digest=$DIGEST" >> $GITHUB_OUTPUT + alpine_digest=$(docker inspect --format='{{index .RepoDigests 0}}' alpine:latest || echo "unknown") + debian_digest=$(docker inspect --format='{{index .RepoDigests 0}}' gitea.fithwum.tech/${{ secrets.GIT_USERNAME }}/debian-base:bookworm || echo "unknown") - - name: Compare digests and update .cache - id: compare_digests + echo "alpine_digest=$alpine_digest" >> $GITHUB_OUTPUT + echo "debian_digest=$debian_digest" >> $GITHUB_OUTPUT + + - name: Compare digests and detect changes + id: check run: | - mkdir -p $CACHE_DIR - - check_digest() { - local name=$1 + check_variant() { + local variant=$1 local new_digest=$2 - local file="$CACHE_DIR/$name.digest" + local infofile="$variant/build-info.json" + local last_digest="" + local base_changed=false + local code_changed=false - echo "[INFO] Checking $name..." - if [[ -f $file ]]; then - old_digest=$(cat "$file") - else - old_digest="" + if [ -f "$infofile" ]; then + last_digest=$(jq -r '.base_digest // empty' "$infofile") fi - if [[ "$old_digest" == "$new_digest" ]]; then - echo "$name_changed=false" >> $GITHUB_OUTPUT - echo "[INFO] $name unchanged." + if [ "$last_digest" != "$new_digest" ]; then + base_changed=true + fi + + if git diff --name-only origin/main...HEAD | grep "^$variant/" > /dev/null; then + code_changed=true + fi + + if [ "$base_changed" = true ] || [ "$code_changed" = true ]; then + echo "$variant_changed=true" >> $GITHUB_OUTPUT else - echo "$new_digest" > "$file" - echo "$name_changed=true" >> $GITHUB_OUTPUT - echo "[INFO] $name changed." + echo "$variant_changed=false" >> $GITHUB_OUTPUT fi } - check_digest "alpine" "${{ steps.alpine_digest.outputs.digest }}" - check_digest "debian-base" "${{ steps.debian_digest.outputs.digest }}" + git fetch origin main - git config user.name "${{ secrets.GIT_USERNAME }}" - git config user.email "${{ secrets.GIT_EMAIL }}" - git add $CACHE_DIR - git commit -m "Update base image digests" || echo "[INFO] No cache changes to commit" - git push || true + check_variant "alpine" "${{ steps.get_digest.outputs.alpine_digest }}" + check_variant "debian" "${{ steps.get_digest.outputs.debian_digest }}" + + build-alpine: + needs: check-for-changes + if: needs.check-for-changes.outputs.should_build_alpine == 'true' + runs-on: doc-docker-build + outputs: + built: 'true' + steps: + - name: Checkout + uses: actions/checkout@v3 - name: Build and Push Alpine Image if: steps.compare_digests.outputs.alpine_changed == 'true' @@ -90,6 +95,16 @@ jobs: echo "[INFO] Building $IMAGE" docker buildx build --platform linux/amd64 --push -t "$IMAGE" ./alpine + build-debian: + needs: check-for-changes + if: needs.check-for-changes.outputs.should_build_debian == 'true' + runs-on: doc-docker-build + outputs: + built: 'true' + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build and Push Debian Image if: steps.compare_digests.outputs.debian-base_changed == 'true' run: | @@ -105,7 +120,10 @@ jobs: docker buildx build --platform linux/amd64 --push -t "$IMAGE" ./basic generate-changelogs: - needs: check-base-images-and-build + needs: check-for-changes + if: | + needs.check-for-changes.outputs.should_build_alpine == 'true' || + needs.check-for-changes.outputs.should_build_debian == 'true' runs-on: doc-docker-build steps: - name: Checkout source @@ -115,10 +133,18 @@ jobs: run: | git clone https://${{ secrets.GIT_USERNAME }}:${{ secrets.GIT_TOKEN }}@gitea.fithwum.tech/fithwum/teamspeak-server.git upload-repo - - name: Generate per-version changelogs + - name: Generate changelogs only for updated variants run: | cd upload-repo - for version in alpine basic debian; do + + if [[ "${{ needs.check-for-changes.outputs.should_build_alpine }}" == "true" ]]; then + versions+=("alpine") + fi + if [[ "${{ needs.check-for-changes.outputs.should_build_debian }}" == "true" ]]; then + versions+=("debian") + fi + + for version in "${versions[@]}"; do echo "[INFO] Updating changelog for $version" changelog="$version/CHANGES.md" @@ -139,7 +165,7 @@ jobs: fi done - - name: Commit and push changelogs if changed + - name: Commit and push changelogs run: | cd upload-repo git config user.name "${{ secrets.GIT_USERNAME }}" @@ -154,7 +180,12 @@ jobs: fi generate-build-info: - needs: generate-changelogs + needs: + - build-alpine + - build-debian + if: | + needs.build-alpine.outputs.built == 'true' || + needs.build-debian.outputs.built == 'true' runs-on: doc-docker-build steps: - name: Checkout source @@ -164,7 +195,13 @@ jobs: run: | git clone https://${{ secrets.GIT_USERNAME }}:${{ secrets.GIT_TOKEN }}@gitea.fithwum.tech/fithwum/teamspeak-server.git upload-repo - - name: Generate build-info.json per version + - name: Generate build-info.json only for updated variants + env: + IMAGE_REGISTRY: ${{ env.IMAGE_REGISTRY }} + IMAGE_ORG: ${{ env.IMAGE_ORG }} + IMAGE_REPO_TS: ${{ env.IMAGE_REPO_TS }} + ALPINE_DIGEST: ${{ needs.check-for-changes.outputs.alpine_digest }} + DEBIAN_DIGEST: ${{ needs.check-for-changes.outputs.debian_digest }} run: | human_size() { local b=$1 @@ -180,21 +217,27 @@ jobs: } cd upload-repo - for version in alpine basic debian; do + declare -A digests + digests[alpine]="${ALPINE_DIGEST}" + digests[debian]="${DEBIAN_DIGEST}" + + versions=() + [[ "${{ needs.check-for-changes.outputs.should_build_alpine }}" == "true" ]] && versions+=("alpine") + [[ "${{ needs.check-for-changes.outputs.should_build_debian }}" == "true" ]] && versions+=("debian") + + for version in "${versions[@]}"; do echo "[INFO] Generating build-info.json for $version" mkdir -p "$version" infofile="$version/build-info.json" - - image="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_ORG }}/${{ env.IMAGE_REPO_TS }}:$version" + image="${IMAGE_REGISTRY}/${IMAGE_ORG}/${IMAGE_REPO_TS}:$version" digest=$(docker inspect --format='{{if .RepoDigests}}{{index .RepoDigests 0}}{{else}}unknown{{end}}' "$image" 2>/dev/null || echo "unknown") size_bytes=$(docker image inspect "$image" --format='{{.Size}}' 2>/dev/null || echo "0") - size_bytes=${size_bytes//[^0-9]/} - if [[ -z "$size_bytes" ]]; then size_bytes=0; fi - size_human=$(human_size "$size_bytes") + base_digest="${digests[$version]:-unknown}" + jq -n \ --arg version "$version" \ --arg commit "$(git rev-parse HEAD)" \ @@ -203,6 +246,7 @@ jobs: --arg digest "$digest" \ --arg image_size "$size_human" \ --argjson image_size_bytes "$size_bytes" \ + --arg base_digest "$base_digest" \ '{ version: $version, commit: $commit, @@ -210,7 +254,8 @@ jobs: image_tag: $image_tag, digest: $digest, image_size: $image_size, - image_size_bytes: $image_size_bytes + image_size_bytes: $image_size_bytes, + base_digest: $base_digest }' > "$infofile" done @@ -225,8 +270,7 @@ jobs: git commit -m "Update build-info on $(date -u +'%Y-%m-%dT%H:%M:%SZ')" git push - # Tag the commit for each version - for version in alpine basic debian; do + for version in alpine debian; do TAG="build-$version" git tag -d "$TAG" 2>/dev/null || true git tag "$TAG" @@ -234,4 +278,4 @@ jobs: done else echo "[INFO] No build-info changes to commit." - fi \ No newline at end of file + fi