@@ -16,55 +16,121 @@ defaults:
1616 run :
1717 shell : bash
1818
19+ env :
20+ REGISTRY_IMAGE : stellar/stellar-cli
21+
1922jobs :
23+ # Resolve the ref to a single immutable SHA and compute the Docker tags once,
24+ # so both platform builds and the published manifest refer to one commit even
25+ # if the branch advances while the workflow runs.
26+ prepare :
27+ runs-on : ubuntu-latest
28+ permissions :
29+ contents : read
30+ outputs :
31+ sha : ${{ steps.resolve.outputs.sha }}
32+ tags : ${{ steps.resolve.outputs.tags }}
33+ steps :
34+ - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
35+ with :
36+ ref : ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
37+ fetch-depth : 0
38+
39+ # Resolve the ref to a SHA and compute Docker tags.
40+ # - Version tag (e.g. v1.2.3): push versioned + latest tags.
41+ # - Any other ref: push a tag for the resolved commit SHA.
42+ - name : Resolve ref and tags
43+ id : resolve
44+ run : |
45+ ref="${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref_name }}"
46+ sha="$(git rev-parse HEAD)"
47+ echo "sha=${sha}" >> $GITHUB_OUTPUT
48+
49+ if [[ "$ref" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
50+ version="${ref#v}"
51+ echo "tags=-t ${REGISTRY_IMAGE}:${version} -t ${REGISTRY_IMAGE}:latest" >> $GITHUB_OUTPUT
52+ elif [[ "${{ github.event_name }}" == "release" ]]; then
53+ echo "::error::Release tag '${ref}' is not a valid version tag (expected vX.Y.Z)."
54+ exit 1
55+ else
56+ echo "tags=-t ${REGISTRY_IMAGE}:${sha}" >> $GITHUB_OUTPUT
57+ fi
58+
59+ # Build each platform on a native runner and push the image by digest.
2060 build :
61+ needs : prepare
2162 strategy :
63+ fail-fast : false
2264 matrix :
2365 include :
2466 - runs-on : ubuntu-latest
25- arch : amd64
67+ platform : linux/ amd64
2668 - runs-on : ubuntu-24.04-arm
27- arch : arm64
69+ platform : linux/ arm64
2870 runs-on : ${{ matrix.runs-on }}
2971 permissions :
3072 contents : read
3173 steps :
74+ - name : Set platform pair
75+ run : |
76+ platform="${{ matrix.platform }}"
77+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
78+
3279 - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3380 with :
34- ref : ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
81+ ref : ${{ needs.prepare.outputs.sha }}
82+
83+ - name : Set up Docker Buildx
84+ uses : docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
3585
36- - name : Install build dependencies
37- run : sudo apt-get update && sudo apt-get install -y --no-install-recommends libudev-dev libdbus-1-dev
86+ - name : Log in to Docker Hub
87+ uses : docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
88+ with :
89+ username : ${{ secrets.DOCKERHUB_USERNAME }}
90+ password : ${{ secrets.DOCKERHUB_TOKEN }}
3891
39- - name : Build binary
40- run : cargo build --package stellar-cli --release
92+ - name : Build and push by digest
93+ id : build
94+ uses : docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
95+ with :
96+ context : .
97+ platforms : ${{ matrix.platform }}
98+ build-args : |
99+ STELLAR_CLI_REV=${{ needs.prepare.outputs.sha }}
100+ outputs : type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
41101
42- - name : Upload binary
102+ - name : Export digest
103+ run : |
104+ mkdir -p "${{ runner.temp }}/digests"
105+ digest="${{ steps.build.outputs.digest }}"
106+ touch "${{ runner.temp }}/digests/${digest#sha256:}"
107+
108+ - name : Upload digest
43109 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
44110 with :
45- name : stellar-${{ matrix.arch }}
46- path : target/release/stellar
111+ name : digests-${{ env.PLATFORM_PAIR }}
112+ path : ${{ runner.temp }}/digests/*
113+ if-no-files-found : error
47114 retention-days : 1
48115
49- docker :
50- needs : build
116+ # Combine the per-platform digests into a single multi-arch manifest list
117+ # and push it under the final tags.
118+ merge :
119+ needs : [prepare, build]
51120 runs-on : ubuntu-latest
52121 permissions :
53122 contents : read
54123 steps :
55124 - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
56125 with :
57- ref : ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
58- fetch-depth : 0
126+ ref : ${{ needs.prepare.outputs.sha }}
59127
60- - name : Download binaries
128+ - name : Download digests
61129 uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
62130 with :
63- pattern : stellar-*
64- merge-multiple : false
65-
66- - name : Set up QEMU
67- uses : docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4
131+ path : ${{ runner.temp }}/digests
132+ pattern : digests-*
133+ merge-multiple : true
68134
69135 - name : Set up Docker Buildx
70136 uses : docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
@@ -75,37 +141,24 @@ jobs:
75141 username : ${{ secrets.DOCKERHUB_USERNAME }}
76142 password : ${{ secrets.DOCKERHUB_TOKEN }}
77143
78- # Compute Docker tags from the ref.
79- # - Version tag (e.g. v1.2.3): push versioned + latest tags.
80- # - Any other ref: push a tag for the resolved commit SHA.
81- - name : Compute tags
144+ - name : Create manifest list and push
145+ working-directory : ${{ runner.temp }}/digests
146+ env :
147+ TAGS : ${{ needs.prepare.outputs. tags }}
82148 run : |
83- ref="${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref_name }}"
84-
85- if [[ "$ref" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
86- version="${ref#v}"
87- echo "DOCKER_TAGS=stellar/stellar-cli:${version},stellar/stellar-cli:latest" >> $GITHUB_ENV
88- elif [[ "${{ github.event_name }}" == "release" ]]; then
89- echo "::error::Release tag '${ref}' is not a valid version tag (expected vX.Y.Z)."
90- exit 1
91- else
92- commit="$(git rev-parse HEAD)"
93- echo "DOCKER_TAGS=stellar/stellar-cli:${commit}" >> $GITHUB_ENV
94- fi
95-
96- - name : Build and push
97- uses : docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
98- with :
99- context : .
100- platforms : linux/amd64,linux/arm64
101- push : true
102- tags : ${{ env.DOCKER_TAGS }}
149+ docker buildx imagetools create ${TAGS} \
150+ $(printf "${REGISTRY_IMAGE}@sha256:%s " *)
103151
104152 - name : Update Docker Hub description
153+ env :
154+ DOCKERHUB_USERNAME : ${{ secrets.DOCKERHUB_USERNAME }}
155+ DOCKERHUB_TOKEN : ${{ secrets.DOCKERHUB_TOKEN }}
105156 run : |
106- TOKEN=$(curl -s -X POST "https://hub.docker.com/v2/users/login/" \
107- -H "Content-Type: application/json" \
108- -d '{"username":"${{ secrets.DOCKERHUB_USERNAME }}","password":"${{ secrets.DOCKERHUB_TOKEN }}"}' \
157+ TOKEN=$(jq -n --arg u "$DOCKERHUB_USERNAME" --arg p "$DOCKERHUB_TOKEN" \
158+ '{username: $u, password: $p}' | \
159+ curl -s -X POST "https://hub.docker.com/v2/users/login/" \
160+ -H "Content-Type: application/json" \
161+ -d @- \
109162 | jq -r .token)
110163
111164 jq -n --arg desc "$(cat ./docker/README.md)" '{"full_description": $desc}' | \
0 commit comments