-
Notifications
You must be signed in to change notification settings - Fork 15
234 lines (226 loc) · 10.5 KB
/
release-upload.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
name: Release Upload
# Pipeline to download binaries from Hydra builds and create GitHub
# releases out of them (or attaching the binaries to an already existing release).
#
# This pipeline is divided in three jobs:
#
# 1. The "wait_for_hydra" job looks up the status of the Hydra build corresponding to
# the tag for which we want to release. If the status is success, the pipeline
# continues. If the status cannot be determined or is a failure, the pipeline stops.
# 2. The "pull" job downloads the binaries from the Hydra build and uploads them as artifacts.
# This job uses a matrix to handle all 3 platforms. Uploading as an artifact allows to
# do the last job without a matrix.
#
# This job uses `--builders "" --max-jobs 0` to ensure the assets are downloaded
# from the IOG cache.
# 3. The "create_release" job downloads the artifacts and attaches them to the target release.
#
# This pipeline is triggered in one of the following 3 ways:
#
# 1. When a release is published, this release's commit must have a tag for the pipeline to succeed
# 2. When a tag is pushed. If this tag has a corresponding release, the release will be augmented.
# If there is no release, it will be created.
# 3. By launching it manually, optionally specifying the tag to release:
# gh workflow run "Release Upload" -r $(git branch --show-current) -f target_tag=cardano-cli-8.22.0.0
# This mode is not supported by the pipeline of cardano-node (which was copied to create this pipeline),
# but we anticipate this mode to be useful when debugging, or releasing a posteriori.
#
# If the tag is not specified, this pipeline will run, but skip the final "create_release" job,
# so no release will get created. This is useful for debugging or
# trying to build a release before tagging it.
#
# So far this pipeline supports releasing Linux and Darwin binaries.
# Please see the "TODO generalize" comments in this file to support new platforms.
on:
workflow_dispatch:
inputs:
target_tag:
description: 'The tag of the release to attach binaries to'
default: ''
required: false
type: string
release:
types:
- published
push:
tags:
- '**'
env:
GH_TOKEN: ${{ github.token }}
jobs:
wait_for_hydra:
name: "Wait for Hydra check-runs"
runs-on: ubuntu-latest
outputs:
TARGET_TAG: ${{ steps.store_vars.outputs.TARGET_TAG }}
DRY_RUN: ${{ steps.store_vars.outputs.DRY_RUN }}
FLAKE_REF: ${{ steps.store_vars.outputs.FLAKE_REF }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Because the target tag may not be HEAD
fetch-tags: true # So that tags are known to git commands
- name: Define target tag, flake ref, and compute drynesss
id: store_vars
run: |
dry_run="false"
if [[ -z "${{ inputs.target_tag }}" ]]
then
# No tag was specified manually as input, take the tag from the current commit (if any)
current_tag=$(git tag --points-at HEAD | head -n 1)
if [[ -z "$current_tag" ]]
then
# No tag was specified manually as input, and current commit has no tag.
echo "Tag not yet defined, using current commit as reference."
target_tag="${{ github.ref_name }}"
echo "Run targets a commit that has no attached tag: no release will be published."
# This is the only case we won't run the create_release job at the end
dry_run="true"
else
# Workflow runs on a commit that has a tag, use this tag
target_tag="$current_tag"
fi
else
# A tag was specified manually as input, use it
target_tag="${{ inputs.target_tag }}"
fi
# Set variables in GITHUB_ENV for next steps and in GITHUB_OUTPUT for next jobs
echo "TARGET_TAG=$target_tag" >> "$GITHUB_ENV"
echo "TARGET_TAG=$target_tag" >> "$GITHUB_OUTPUT"
flake_ref="github:${{ github.repository }}/$target_tag"
echo "FLAKE_REF=$flake_ref" >> "$GITHUB_OUTPUT"
echo "DRY_RUN=$dry_run" >> "$GITHUB_OUTPUT"
- name: Get specific check run status
timeout-minutes: 120
run: |
while true; do
conclusion=$(gh api "repos/$GITHUB_REPOSITORY/commits/${{ env.TARGET_TAG }}/check-runs" --jq '.check_runs[] | select(.name | test("ci/hydra-build:.*\\.required")) | .conclusion')
# Here we are being careful, because we query the status of multiple jobs (once per line)
# But the only thing we are sure is that "success" means a green job. There
# could be unknown statuses, which is why we may retry when unsure (see 'sleep') below.
echo "ci/hydra-build:.*\\.required returned status: $conclusion"
# conclusion is of the form (note the newlines, which matter because we use 'wc -l' below)
# success
# failure
# success
# Because we care of the newlines, quoting $conclusion with "" is especially important below!
# (see https://stackoverflow.com/questions/22101778/how-to-preserve-line-breaks-when-storing-command-output-to-a-variable)
# shellcheck disable=SC2126
num_failure=$(echo "$conclusion" | grep "^failure" | wc -l)
num_status=$(echo "$conclusion" | wc -l)
# shellcheck disable=SC2126
num_success=$(echo "$conclusion" | grep "^success" | wc -l)
echo "num_failure=$num_failure num_status=$num_status num_success=$num_success"
if [[ "$num_failure" != "0" ]]; then
echo "ci/hydra-build:required failed"
exit 1
elif [[ "$num_status" == "$num_success" ]]; then
echo "ci/hydra-build:required succeeded"
exit 0
else
# Unclear (some non-failure, non-success)
echo "ci/hydra-build:required pending with $conclusion. Waiting 30s..."
sleep 30
fi
done
pull:
needs: [wait_for_hydra]
strategy:
matrix:
# TODO generalize
arch: [x86_64-linux, x86_64-darwin, aarch64-darwin, aarch64-linux]
name: "Download Asset"
runs-on: ubuntu-latest
steps:
- name: Install Nix with good defaults
uses: input-output-hk/install-nix-action@v20
with:
extra_nix_config: |
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=
substituters = https://cache.iog.io/ https://cache.nixos.org/
nix_path: nixpkgs=channel:nixos-unstable
- name: Display flake metadata
id: flake-metadata
run: |
nix flake metadata "${{ needs.wait_for_hydra.outputs.FLAKE_REF }}"
nix flake metadata "${{ needs.wait_for_hydra.outputs.FLAKE_REF }}" --json | jq -r '"LOCKED_URL=\(.url)"' >> "$GITHUB_ENV"
- name: Build
run: |
derivation="hydraJobs."
case ${{ matrix.arch }} in
"x86_64-darwin" | "aarch64-darwin")
derivation+="${{ matrix.arch }}"
;;
"x86_64-linux")
derivation+="x86_64-linux.ghc965-x86_64-unknown-linux-musl"
;;
"aarch64-linux")
derivation+="x86_64-linux.ghc965-aarch64-unknown-linux-musl"
;;
*)
echo "Unexpected matrix.arch value: ${{ matrix.arch }}"
exit 1
;;
esac
derivation+=".packages.cardano-cli:exe:cardano-cli"
nix build --builders "" --max-jobs 0 ${{ env.LOCKED_URL }}#$derivation
tree result
cp result/bin/cardano-cli cardano-cli-${{ matrix.arch }} # (1)
- uses: actions/upload-artifact@v4
with:
name: cardano-cli-${{ matrix.arch }}
path: cardano-cli-* # Should match (1)
retention-days: 1
create_release:
needs: [wait_for_hydra, pull]
name: "Create Release"
runs-on: ubuntu-latest
if: ${{ needs.wait_for_hydra.outputs.DRY_RUN == 'false' }}
steps:
- uses: actions/checkout@v4 # We need the repo to execute extract-changelog.sh below
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Compress
run: |
# (2)
# TARGET_TAG is of the form cardano-cli-8.22.0, so we don't need to prefix the tar.gz's name
# with cardano-cli
for arch in x86_64-linux x86_64-darwin aarch64-darwin aarch64-linux; do
tar -czf ${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-$arch.tar.gz cardano-cli-$arch
done
# TODO generalize
# zip ${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-win64.zip cardano-cli-win64
- name: Checksums
run: |
# (3)
for arch in x86_64-linux x86_64-darwin aarch64-darwin aarch64-linux; do
sha256sum ${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-$arch.tar.gz >> ${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-sha256sums.txt
done
- name: Create short tag
run: |
# Transform the long tag (e.g. "cardano-cli-8.22.0.0")
# into the short version (e.g. "8.22.0.0")
long_tag=${{ needs.wait_for_hydra.outputs.TARGET_TAG }}
short_tag="${long_tag#cardano-cli-}"
echo "SHORT_TAG=$short_tag" >> "$GITHUB_ENV"
- name: Create changelog
run: |
echo -e "# Changelog\n" > RELEASE_CHANGELOG.md
./scripts/ci/extract-changelog.sh ${{ env.SHORT_TAG }} >> RELEASE_CHANGELOG.md
- name: Create Release
uses: input-output-hk/action-gh-release@v1
with:
draft: true
tag_name: ${{ needs.wait_for_hydra.outputs.TARGET_TAG }} # Git tag the release is attached to
name: ${{ env.SHORT_TAG }} # Release name in GitHub UI
# TODO generalize
# cardano-cli-${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-win64.zip
# All entries in 'files' below should match (2) and (3)
files: |
${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-x86_64-linux.tar.gz
${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-x86_64-darwin.tar.gz
${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-aarch64-darwin.tar.gz
${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-aarch64-linux.tar.gz
${{ needs.wait_for_hydra.outputs.TARGET_TAG }}-sha256sums.txt
body_path: RELEASE_CHANGELOG.md