Skip to content

Commit 269b89c

Browse files
docker images
1 parent a89c583 commit 269b89c

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
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=$(gh api repos/$GITHUB_REPOSITORY/releases/latest --paginate --jq '.tag_name')
72+
echo "LATEST_TAG=$LATEST_TAG" >> "$GITHUB_OUTPUT"
73+
echo "Latest release tag is: $LATEST_TAG"
74+
75+
76+
build:
77+
needs: [prepare]
78+
name: "Upload to ghcr.io"
79+
runs-on: ubuntu-latest
80+
strategy:
81+
matrix:
82+
arch:
83+
- name: amd64
84+
system: x86_64-linux
85+
- name: arm64
86+
system: aarch64-linux
87+
image:
88+
- name: dmq-node
89+
nix_key: docker-hydra
90+
91+
steps:
92+
- name: Install Nix
93+
uses: cachix/install-nix-action@v31
94+
95+
- name: Log in to GitHub Container Registry
96+
uses: docker/login-action@v3
97+
with:
98+
registry: ghcr.io
99+
username: ${{ github.actor }}
100+
password: ${{ secrets.GITHUB_TOKEN }}
101+
102+
# NOTE We assume that hydra has already built the image, this is
103+
# reasonable since, before applying the tag, we must have already
104+
# pushed the tagged commit somewhere, and Hydra will have had the
105+
# change to build the image.
106+
107+
- name: Uploading ${{ matrix.image.name }} (${{ matrix.arch.name }})
108+
run: |
109+
echo "::group::Downloading from cache"
110+
nix build \
111+
--accept-flake-config \
112+
--print-out-paths \
113+
--builders "" \
114+
--max-jobs 0 \
115+
--out-link ./result-${{ matrix.image.name }}-${{ matrix.arch.name }} \
116+
${{ needs.prepare.outputs.LOCKED_URL }}#packages.${{ matrix.arch.system }}.${{ matrix.image.nix_key }}
117+
echo "::endgroup::"
118+
119+
echo "::group::Uploading to registry"
120+
skopeo copy \
121+
docker-archive:./result-${{ matrix.image.name }}-${{ matrix.arch.name }} \
122+
docker://ghcr.io/intersectmbo/${{ matrix.image.name }}:$GITHUB_REF_NAME-${{ matrix.arch.name }}
123+
echo "::endgroup::"
124+
125+
126+
create-manifest:
127+
needs: [prepare, build]
128+
name: "Create Multi-Arch Manifest"
129+
runs-on: ubuntu-latest
130+
131+
steps:
132+
- name: Install Nix
133+
uses: cachix/install-nix-action@v31
134+
135+
# Regctl simplifies obtaining multi-arch digests
136+
- name: Install Nix Profile Commands
137+
run: nix profile install nixpkgs#regctl
138+
139+
# The docker buildx action has a tight coupling with GH runners
140+
- name: Setup Docker Buildx
141+
uses: docker/setup-buildx-action@v3
142+
143+
- name: Show buildx configuration
144+
run: docker buildx ls
145+
146+
- name: Log in to GitHub Container Registry
147+
uses: docker/login-action@v3
148+
with:
149+
registry: ghcr.io
150+
username: ${{ github.actor }}
151+
password: ${{ secrets.GITHUB_TOKEN }}
152+
153+
- name: Create Manifests
154+
run: |
155+
REPOS=(cardano-node cardano-submit-api cardano-tracer)
156+
ARCHES=(amd64 arm64)
157+
158+
for REPO in "${REPOS[@]}"; do
159+
IMAGE_REPO="ghcr.io/intersectmbo/$REPO"
160+
DIGESTS=()
161+
162+
echo "::group::Fetching digests for $REPO"
163+
for ARCH in "${ARCHES[@]}"; do
164+
DIGEST=$(skopeo inspect --no-tags "docker://$IMAGE_REPO:$GITHUB_REF_NAME-$ARCH" | jq -r .Digest)
165+
echo "$REPO $ARCH digest: $DIGEST"
166+
DIGESTS+=("$IMAGE_REPO@$DIGEST")
167+
done
168+
echo "::endgroup::"
169+
170+
echo "::group::Creating manifest for $REPO:$GITHUB_REF_NAME"
171+
docker buildx imagetools create --tag "$IMAGE_REPO:$GITHUB_REF_NAME" "${DIGESTS[@]}"
172+
echo "::endgroup::"
173+
done
174+
175+
- name: Verify multi-arch manifests
176+
run: |
177+
for REPO in cardano-node cardano-submit-api cardano-tracer; do
178+
IMAGE_REPO="ghcr.io/intersectmbo/$REPO"
179+
echo "::group::Inspecting $REPO:$GITHUB_REF_NAME"
180+
181+
DIGEST=$(regctl manifest head "$IMAGE_REPO:$GITHUB_REF_NAME")
182+
echo "$REPO multi-arch manifest digest: $DIGEST"
183+
skopeo inspect --raw "docker://$IMAGE_REPO:$GITHUB_REF_NAME" | jq
184+
185+
echo "::endgroup::"
186+
done
187+
188+
- name: Tag Containers as :latest
189+
# Github releases are checked for latest tag in the first `or` operand of
190+
# the if statement. However, promoted pre-releases or changed full
191+
# releases do not count as a `published` event and so won't trigger
192+
# this workflow. For those use cases a manual workflow must be run
193+
# from the matching release tag which the second `or` operand checks
194+
# for.
195+
if: |
196+
(github.event_name == 'release' && github.event.release.tag_name == needs.prepare.outputs.LATEST_TAG) ||
197+
(github.event_name == 'workflow_dispatch' && github.ref == format('refs/tags/{0}', needs.prepare.outputs.LATEST_TAG))
198+
run: |
199+
REPOS=(cardano-node cardano-submit-api cardano-tracer)
200+
201+
for REPO in "${REPOS[@]}"; do
202+
IMAGE_REPO="ghcr.io/intersectmbo/$REPO"
203+
DIGEST=$(regctl manifest head "$IMAGE_REPO:$GITHUB_REF_NAME")
204+
205+
echo "::group::Creating manifest for $IMAGE_REPO:latest"
206+
docker buildx imagetools create --tag "$IMAGE_REPO:latest" "$IMAGE_REPO@$DIGEST"
207+
echo "::endgroup::"
208+
done

nix/outputs.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@ let
2424
# (inputs.self.rev or inputs.self.dirtyShortRev)
2525
project.projectCross.musl64.hsPkgs.dmq-node.components.exes.dmq-node;
2626
default = dmq-node;
27+
docker-dmq = pkgs.dockerTools.buildImage {
28+
name = "docker-dmq";
29+
tag = "latest";
30+
created = "now";
31+
copyToRoot = pkgs.buildEnv {
32+
name = "dmq-env";
33+
paths = [
34+
pkgs.busybox
35+
pkgs.dockerTools.caCertificates
36+
];
37+
};
38+
config = {
39+
Entrypoint = [ "${packages.dmq-node-static}/bin/dmq-node-static" ];
40+
};
41+
};
2742
};
2843

2944
app = {

0 commit comments

Comments
 (0)