1+ name : Upload to ghcr.io
2+
3+ on :
4+ push :
5+ tags :
6+ - ' **'
7+ # GITHUB_SHA: Last commit in the tagged release
8+ # GITHUB_REF: Tag ref of release refs/tags/<tag_name>
9+ release :
10+ types :
11+ - published
12+ # GITHUB_SHA: Last commit on the GITHUB_REF branch or tag
13+ # GITHUB_REF: Branch or tag that received dispatch
14+ workflow_dispatch : {}
15+
16+ permissions :
17+ contents : read
18+ packages : write
19+
20+ env :
21+ # Only to avoid some repetition
22+ FLAKE_REF : github:${{ github.repository }}/${{ github.ref_name }}
23+ GH_TOKEN : ${{ github.token }}
24+
25+ jobs :
26+ wait-for-hydra :
27+ name : " Wait for hydra check-runs"
28+ runs-on : ubuntu-latest
29+
30+ steps :
31+ - name : Waiting for ci/hydra-build:x86_64-linux.required to complete
32+ run : |
33+ while [[ true ]]; do
34+ check_name='ci/hydra-build:x86_64-linux.required'
35+ conclusion=$(gh api "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/check-runs?check_name=$check_name" --paginate --jq '.check_runs[].conclusion')
36+ case "$conclusion" in
37+ success)
38+ echo "$check_name succeeded"
39+ exit 0;;
40+ '')
41+ echo "$check_name pending. Waiting 30s..."
42+ sleep 30;;
43+ *)
44+ echo "$check_name terminated unsuccessfully"
45+ exit 1;;
46+ esac
47+ done
48+
49+
50+ prepare :
51+ needs : [wait-for-hydra]
52+ name : " Prepare metadata"
53+ runs-on : ubuntu-latest
54+ outputs :
55+ LATEST_TAG : ${{ steps.latest-tag.outputs.LATEST_TAG }}
56+ LOCKED_URL : ${{ steps.flake-metadata.outputs.LOCKED_URL }}
57+
58+ steps :
59+ - name : Install Nix
60+ uses : cachix/install-nix-action@v31
61+
62+ - name : Display flake metadata
63+ id : flake-metadata
64+ run : |
65+ nix flake metadata ${{ env.FLAKE_REF }}
66+ nix flake metadata ${{ env.FLAKE_REF }} --json | jq -r '"LOCKED_URL=\(.url)"' >> "$GITHUB_OUTPUT"
67+
68+ - name : Obtaining latest release tag
69+ id : latest-tag
70+ run : |
71+ LATEST_TAG=0.2.0.0
72+ # LATEST_TAG=$(gh api repos/$GITHUB_REPOSITORY/releases/latest --paginate --jq '.tag_name')
73+ # echo "LATEST_TAG=$LATEST_TAG" >> "$GITHUB_OUTPUT"
74+ # echo "Latest release tag is: $LATEST_TAG"
75+
76+
77+ build :
78+ needs : [prepare]
79+ name : " Upload to ghcr.io"
80+ runs-on : ubuntu-latest
81+ strategy :
82+ matrix :
83+ arch :
84+ - name : amd64
85+ system : x86_64-linux
86+ image :
87+ - name : dmq-node
88+ nix_key : docker-dmq
89+
90+ steps :
91+ - name : Install Nix
92+ uses : cachix/install-nix-action@v31
93+
94+ - name : Log in to GitHub Container Registry
95+ uses : docker/login-action@v3
96+ with :
97+ registry : ghcr.io
98+ username : ${{ github.actor }}
99+ password : ${{ secrets.GITHUB_TOKEN }}
100+
101+ # NOTE We assume that hydra has already built the image, this is
102+ # reasonable since, before applying the tag, we must have already
103+ # pushed the tagged commit somewhere, and Hydra will have had the
104+ # change to build the image.
105+
106+ - name : Uploading ${{ matrix.image.name }} (${{ matrix.arch.name }})
107+ run : |
108+ echo "::group::Downloading from cache"
109+ nix build \
110+ --accept-flake-config \
111+ --print-out-paths \
112+ --builders "" \
113+ --max-jobs 0 \
114+ --out-link ./result-${{ matrix.image.name }}-${{ matrix.arch.name }} \
115+ ${{ needs.prepare.outputs.LOCKED_URL }}#packages.${{ matrix.arch.system }}.${{ matrix.image.nix_key }}
116+ echo "::endgroup::"
117+
118+ echo "::group::Uploading to registry"
119+ skopeo copy \
120+ docker-archive:./result-${{ matrix.image.name }}-${{ matrix.arch.name }} \
121+ docker://ghcr.io/intersectmbo/${{ matrix.image.name }}:$GITHUB_REF_NAME-${{ matrix.arch.name }}
122+ echo "::endgroup::"
123+
124+
125+ create-manifest :
126+ needs : [prepare, build]
127+ name : " Create Multi-Arch Manifest"
128+ runs-on : ubuntu-latest
129+
130+ steps :
131+ - name : Install Nix
132+ uses : cachix/install-nix-action@v31
133+
134+ # Regctl simplifies obtaining multi-arch digests
135+ - name : Install Nix Profile Commands
136+ run : nix profile install nixpkgs#regctl
137+
138+ # The docker buildx action has a tight coupling with GH runners
139+ - name : Setup Docker Buildx
140+ uses : docker/setup-buildx-action@v3
141+
142+ - name : Show buildx configuration
143+ run : docker buildx ls
144+
145+ - name : Log in to GitHub Container Registry
146+ uses : docker/login-action@v3
147+ with :
148+ registry : ghcr.io
149+ username : ${{ github.actor }}
150+ password : ${{ secrets.GITHUB_TOKEN }}
151+
152+ - name : Create Manifests
153+ run : |
154+ REPOS=(dmq-node)
155+ ARCHES=(amd64)
156+
157+ for REPO in "${REPOS[@]}"; do
158+ IMAGE_REPO="ghcr.io/intersectmbo/$REPO"
159+ DIGESTS=()
160+
161+ echo "::group::Fetching digests for $REPO"
162+ for ARCH in "${ARCHES[@]}"; do
163+ DIGEST=$(skopeo inspect --no-tags "docker://$IMAGE_REPO:$GITHUB_REF_NAME-$ARCH" | jq -r .Digest)
164+ echo "$REPO $ARCH digest: $DIGEST"
165+ DIGESTS+=("$IMAGE_REPO@$DIGEST")
166+ done
167+ echo "::endgroup::"
168+
169+ echo "::group::Creating manifest for $REPO:$GITHUB_REF_NAME"
170+ docker buildx imagetools create --tag "$IMAGE_REPO:$GITHUB_REF_NAME" "${DIGESTS[@]}"
171+ echo "::endgroup::"
172+ done
173+
174+ - name : Verify multi-arch manifests
175+ run : |
176+ for REPO in dmq-node; do
177+ IMAGE_REPO="ghcr.io/intersectmbo/$REPO"
178+ echo "::group::Inspecting $REPO:$GITHUB_REF_NAME"
179+
180+ DIGEST=$(regctl manifest head "$IMAGE_REPO:$GITHUB_REF_NAME")
181+ echo "$REPO multi-arch manifest digest: $DIGEST"
182+ skopeo inspect --raw "docker://$IMAGE_REPO:$GITHUB_REF_NAME" | jq
183+
184+ echo "::endgroup::"
185+ done
186+
187+ - name : Tag Containers as :latest
188+ # Github releases are checked for latest tag in the first `or` operand of
189+ # the if statement. However, promoted pre-releases or changed full
190+ # releases do not count as a `published` event and so won't trigger
191+ # this workflow. For those use cases a manual workflow must be run
192+ # from the matching release tag which the second `or` operand checks
193+ # for.
194+ if : |
195+ (github.event_name == 'release' && github.event.release.tag_name == needs.prepare.outputs.LATEST_TAG) ||
196+ (github.event_name == 'workflow_dispatch' && github.ref == format('refs/tags/{0}', needs.prepare.outputs.LATEST_TAG))
197+ run : |
198+ REPOS=(dmq-node)
199+
200+ for REPO in "${REPOS[@]}"; do
201+ IMAGE_REPO="ghcr.io/intersectmbo/$REPO"
202+ DIGEST=$(regctl manifest head "$IMAGE_REPO:$GITHUB_REF_NAME")
203+
204+ echo "::group::Creating manifest for $IMAGE_REPO:latest"
205+ docker buildx imagetools create --tag "$IMAGE_REPO:latest" "$IMAGE_REPO@$DIGEST"
206+ echo "::endgroup::"
207+ done
0 commit comments