Skip to content

Commit bf955e2

Browse files
committed
Add ./branches.sh to generate the build matrix
`./branches.sh` will print an error when a new milestone is released, but wasn't added to `container.env` yet. We won't attempt to build that milestone, but rather let the new "Generate jobs" job fail. This failure will cause GitHub to send us a notification. However, we still proceed with building the configured milestones. The milestones to build are now configured in \`container.env\`, not in the GitHub workflow manifest.
1 parent fb8b703 commit bf955e2

File tree

5 files changed

+175
-23
lines changed

5 files changed

+175
-23
lines changed

.github/workflows/container-auto-update.yml

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,60 @@ defaults:
1515
shell: bash -eu -o pipefail {0}
1616

1717
jobs:
18+
generate-jobs:
19+
name: Generate jobs
20+
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
25+
outputs:
26+
BUILD_MATRIX: ${{ steps.generate-jobs.outputs.BUILD_MATRIX }}
27+
28+
steps:
29+
- name: Setup CI tools
30+
run: |
31+
. <(curl -fsS -L "$CI_TOOLS_SETUP" | bash -s ~/ci-tools)
32+
echo "CI_TOOLS=$CI_TOOLS" | tee -a "$GITHUB_ENV"
33+
echo "CI_TOOLS_PATH=$CI_TOOLS_PATH" | tee -a "$GITHUB_ENV"
34+
35+
- name: Checkout repository
36+
uses: actions/checkout@v4
37+
38+
- name: Generate jobs
39+
id: generate-jobs
40+
run: |
41+
MILESTONES="$(./branches.sh)" || EXIT_CODE=$?
42+
43+
echo ::group::Jobs list
44+
echo "$MILESTONES"
45+
echo ::endgroup::
46+
47+
echo "BUILD_MATRIX=$([ -z "$MILESTONES" ] || jq -Rcn '{"MILESTONE": [inputs]}' <<< "$MILESTONES")" >> $GITHUB_OUTPUT
48+
exit ${EXIT_CODE:-0}
49+
1850
build:
51+
name: Build & publish container
52+
53+
needs: generate-jobs
54+
if: ${{ always() && needs.generate-jobs.outputs.BUILD_MATRIX }}
55+
1956
runs-on: ubuntu-latest
2057
permissions:
2158
contents: read
2259
packages: write
2360

61+
concurrency: build-${{ matrix.MILESTONE }}
62+
2463
strategy:
25-
matrix:
26-
BUILD_REF:
27-
- refs/heads/main
28-
BASE_IMAGE:
29-
- docker.io/debian:bookworm
30-
- docker.io/debian:bullseye
31-
- docker.io/debian:trixie
64+
matrix: ${{ fromJSON(needs.generate-jobs.outputs.BUILD_MATRIX) }}
3265
fail-fast: false
33-
max-parallel: 1
3466

3567
env:
3668
REGISTRY: ghcr.io
3769
OWNER: sgsgermany
3870
IMAGE: debian
39-
BUILD_REF: ${{ matrix.BUILD_REF }}
40-
BASE_IMAGE: ${{ matrix.BASE_IMAGE }}
71+
MILESTONE: ${{ matrix.MILESTONE }}
4172

4273
steps:
4374
- name: Setup CI tools
@@ -48,8 +79,6 @@ jobs:
4879
4980
- name: Checkout repository
5081
uses: actions/checkout@v4
51-
with:
52-
ref: ${{ env.BUILD_REF }}
5382

5483
- name: Log into container registry ${{ env.REGISTRY }}
5584
uses: redhat-actions/podman-login@v1

.github/workflows/container-publish.yml

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ name: Build & publish container
33
on:
44
push:
55
branches: [ main ]
6-
workflow_dispatch: {}
6+
workflow_dispatch:
7+
inputs:
8+
branch:
9+
description: Debian version branch
10+
required: false
11+
type: string
712

813
concurrency: build
914

@@ -15,24 +20,62 @@ defaults:
1520
shell: bash -eu -o pipefail {0}
1621

1722
jobs:
23+
generate-jobs:
24+
name: Generate jobs
25+
26+
runs-on: ubuntu-latest
27+
permissions:
28+
contents: read
29+
30+
outputs:
31+
BUILD_MATRIX: ${{ steps.generate-jobs.outputs.BUILD_MATRIX }}
32+
33+
steps:
34+
- name: Setup CI tools
35+
run: |
36+
. <(curl -fsS -L "$CI_TOOLS_SETUP" | bash -s ~/ci-tools)
37+
echo "CI_TOOLS=$CI_TOOLS" | tee -a "$GITHUB_ENV"
38+
echo "CI_TOOLS_PATH=$CI_TOOLS_PATH" | tee -a "$GITHUB_ENV"
39+
40+
- name: Checkout repository
41+
uses: actions/checkout@v4
42+
43+
- name: Generate jobs
44+
id: generate-jobs
45+
env:
46+
MILESTONES: ${{ inputs.branch }}
47+
run: |
48+
[ -n "$MILESTONES" ] || { MILESTONES="$(./branches.sh)" || EXIT_CODE=$?; }
49+
50+
echo ::group::Jobs list
51+
echo "$MILESTONES"
52+
echo ::endgroup::
53+
54+
echo "BUILD_MATRIX=$([ -z "$MILESTONES" ] || jq -Rcn '{"MILESTONE": [inputs]}' <<< "$MILESTONES")" >> $GITHUB_OUTPUT
55+
exit ${EXIT_CODE:-0}
56+
1857
build:
58+
name: Build & publish container
59+
60+
needs: generate-jobs
61+
if: ${{ always() && needs.generate-jobs.outputs.BUILD_MATRIX }}
62+
1963
runs-on: ubuntu-latest
2064
permissions:
2165
contents: read
2266
packages: write
2367

68+
concurrency: build-${{ matrix.MILESTONE }}
69+
2470
strategy:
25-
matrix:
26-
BASE_IMAGE:
27-
- docker.io/debian:bookworm
28-
- docker.io/debian:bullseye
29-
- docker.io/debian:trixie
71+
matrix: ${{ fromJSON(needs.generate-jobs.outputs.BUILD_MATRIX) }}
72+
fail-fast: false
3073

3174
env:
3275
REGISTRY: ghcr.io
3376
OWNER: sgsgermany
3477
IMAGE: debian
35-
BASE_IMAGE: ${{ matrix.BASE_IMAGE }}
78+
MILESTONE: ${{ matrix.MILESTONE }}
3679

3780
steps:
3881
- name: Setup CI tools

branches.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/bash
2+
# Debian GNU/Linux
3+
# @SGSGermany's base image for containers based on Debian GNU/Linux.
4+
#
5+
# Copyright (c) 2022 SGS Serious Gaming & Simulations GmbH
6+
#
7+
# This work is licensed under the terms of the MIT license.
8+
# For a copy, see LICENSE file or <https://opensource.org/licenses/MIT>.
9+
#
10+
# SPDX-License-Identifier: MIT
11+
# License-Filename: LICENSE
12+
13+
set -eu -o pipefail
14+
export LC_ALL=C.UTF-8
15+
16+
[ -v CI_TOOLS ] && [ "$CI_TOOLS" == "SGSGermany" ] \
17+
|| { echo "Invalid build environment: Environment variable 'CI_TOOLS' not set or invalid" >&2; exit 1; }
18+
19+
[ -v CI_TOOLS_PATH ] && [ -d "$CI_TOOLS_PATH" ] \
20+
|| { echo "Invalid build environment: Environment variable 'CI_TOOLS_PATH' not set or invalid" >&2; exit 1; }
21+
22+
[ -x "$(type -P skopeo 2>/dev/null)" ] \
23+
|| { echo "Missing script dependency: skopeo" >&2; exit 1; }
24+
25+
[ -x "$(type -P jq 2>/dev/null)" ] \
26+
|| { echo "Missing script dependency: jq" >&2; exit 1; }
27+
28+
source "$CI_TOOLS_PATH/helper/common.sh.inc"
29+
30+
BUILD_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
31+
source "$BUILD_DIR/container.env"
32+
33+
EXIT_CODE=0
34+
35+
echo + "BRANCHES_LOCAL=\"\$(printf '%s\n' \"\${MILESTONES[@]}\" | sort_semver)\"" >&2
36+
BRANCHES_LOCAL="$(printf '%s\n' "${MILESTONES[@]}" | sort_semver)"
37+
38+
echo + "LATEST_BRANCH=\"\$(head -n 1 <<< \"\$BRANCHES_LOCAL\")\"" >&2
39+
LATEST_BRANCH="$(head -n 1 <<< "$BRANCHES_LOCAL")"
40+
41+
echo + "BRANCHES_GLOBAL_JSON=\"\$(skopeo list-tags $(quote "docker://${BASE_IMAGE%:*}"))\"" >&2
42+
BRANCHES_GLOBAL_JSON="$(skopeo list-tags "docker://${BASE_IMAGE%:*}" || true)"
43+
44+
if ! jq -e '.Tags[]' &> /dev/null <<< "$BRANCHES_GLOBAL_JSON"; then
45+
echo "Unable to read image tags from container repository 'docker://${BASE_IMAGE%:*}'" >&2
46+
exit 2
47+
fi
48+
49+
echo + "BRANCHES_GLOBAL=\"\$(jq -re '.Tags[]|select(test(\"^[0-9]+$\"))' <<< \"\$BRANCHES_GLOBAL_JSON\" | sort_semver)\"" >&2
50+
BRANCHES_GLOBAL="$(jq -re '.Tags[]|select(test("^[0-9]+$"))' <<< "$BRANCHES_GLOBAL_JSON" | sort_semver)"
51+
52+
echo + "BRANCHES_MISSING=\"\$(awk -v latest=$(quote "$LATEST_BRANCH") '\$0 == latest { found=1; next } found { print }'\" < <(tac <<< \"\$BRANCHES_GLOBAL\")" >&2
53+
BRANCHES_MISSING="$(awk -v latest="$LATEST_BRANCH" '$0 == latest { found=1; next } found { print }' < <(tac <<< "$BRANCHES_GLOBAL"))"
54+
55+
if [ -n "$BRANCHES_MISSING" ]; then
56+
echo "Explicit build instructions for the following Debian branches are missing" >&2
57+
sed -e 's/^/- /' <<< "$BRANCHES_MISSING" >&2
58+
EXIT_CODE=1
59+
fi
60+
61+
echo + "echo \"\$BRANCHES_LOCAL\"" >&2
62+
[ -z "$BRANCHES_LOCAL" ] || echo "$BRANCHES_LOCAL"
63+
64+
exit $EXIT_CODE

container.env

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
MILESTONE="${MILESTONE:-latest}"
2+
MILESTONES=(
3+
13 # trixie
4+
12 # bookworm
5+
11 # bullseye
6+
)
7+
18
REGISTRY="${REGISTRY:-ghcr.io}"
29
OWNER="${OWNER:-sgsgermany}"
310
IMAGE="${IMAGE:-debian}"
411
TAGS="${TAGS:-latest}"
512

6-
BASE_IMAGE="${BASE_IMAGE:-docker.io/debian:latest}"
13+
BASE_IMAGE="${BASE_IMAGE:-docker.io/debian:$MILESTONE}"

tags.sh

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ export LC_ALL=C.UTF-8
1919
[ -v CI_TOOLS_PATH ] && [ -d "$CI_TOOLS_PATH" ] \
2020
|| { echo "Invalid build environment: Environment variable 'CI_TOOLS_PATH' not set or invalid" >&2; exit 1; }
2121

22+
[ -x "$(type -P podman 2>/dev/null)" ] \
23+
|| { echo "Missing script dependency: podman" >&2; exit 1; }
24+
25+
[ -x "$(type -P skopeo 2>/dev/null)" ] \
26+
|| { echo "Missing script dependency: skopeo" >&2; exit 1; }
27+
28+
[ -x "$(type -P jq 2>/dev/null)" ] \
29+
|| { echo "Missing script dependency: jq" >&2; exit 1; }
30+
2231
source "$CI_TOOLS_PATH/helper/common.sh.inc"
2332

2433
BUILD_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
@@ -65,14 +74,14 @@ fi
6574
ls_versions() {
6675
jq -re --arg "VERSION" "$1" \
6776
'.Tags[]|select(test("^[0-9]+\\.[0-9]+$") and startswith($VERSION + "."))' \
68-
<<<"$BASE_IMAGE_REPO_TAGS" | sort_semver
77+
<<< "$BASE_IMAGE_REPO_TAGS" | sort_semver
6978
}
7079

7180
echo + "BASE_IMAGE_REPO_TAGS=\"\$(skopeo list-tags $(quote "docker://${BASE_IMAGE%:*}"))\"" >&2
7281
BASE_IMAGE_REPO_TAGS="$(skopeo list-tags "docker://${BASE_IMAGE%:*}" || true)"
7382

74-
if [ -z "$BASE_IMAGE_REPO_TAGS" ]; then
75-
echo "Unable to read tags from container repository 'docker://${BASE_IMAGE%:*}'" >&2
83+
if ! jq -e '.Tags[]' &> /dev/null <<< "$BASE_IMAGE_REPO_TAGS"; then
84+
echo "Unable to read image tags from container repository 'docker://${BASE_IMAGE%:*}'" >&2
7685
exit 1
7786
fi
7887

0 commit comments

Comments
 (0)