-
Notifications
You must be signed in to change notification settings - Fork 0
145 lines (135 loc) · 5.63 KB
/
Copy pathrelease.yml
File metadata and controls
145 lines (135 loc) · 5.63 KB
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
name: Release
on:
workflow_dispatch:
inputs:
version:
description: Release version using vX.Y.Z.
required: true
type: string
manual_validation_confirmed:
description: Confirm that the Apps completed manual interactive validation.
required: true
default: false
type: boolean
permissions:
contents: read
actions: read
concurrency:
group: release-${{ inputs.version }}
cancel-in-progress: false
jobs:
validate-request:
name: Validate manual release request
runs-on: ubuntu-latest
outputs:
version: ${{ steps.request.outputs.version }}
steps:
- name: Validate branch, version, confirmation, CI, and remote state
id: request
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.version }}
RELEASE_SHA: ${{ github.sha }}
MANUAL_VALIDATION_CONFIRMED: ${{ inputs.manual_validation_confirmed }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "::error::Release must be dispatched from main."
exit 1
fi
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release version must use vX.Y.Z."
exit 1
fi
if [[ "$MANUAL_VALIDATION_CONFIRMED" != "true" ]]; then
echo "::error::Complete manual App validation before starting release."
exit 1
fi
if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${RELEASE_TAG}" >/dev/null 2>&1; then
echo "::error::Tag ${RELEASE_TAG} already exists."
exit 1
fi
if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo "::error::Release ${RELEASE_TAG} already exists."
exit 1
fi
ci_run_id="$(gh api \
"repos/${GITHUB_REPOSITORY}/actions/workflows/ci.yml/runs?head_sha=${RELEASE_SHA}&event=push&status=success&per_page=1" \
--jq '.workflow_runs[0].id // empty')"
if [[ -z "$ci_run_id" ]]; then
echo "::error::The exact main commit has no successful integration-policy push run."
exit 1
fi
echo "version=${RELEASE_TAG}" >> "$GITHUB_OUTPUT"
echo "Using successful exact-commit integration record: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${ci_run_id}" \
>> "$GITHUB_STEP_SUMMARY"
create-draft:
name: Create validated tag and draft release
needs: validate-request
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Check out the validated commit
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.sha }}
- name: Create annotated tag and stage launcher from its blob
env:
RELEASE_TAG: ${{ needs.validate-request.outputs.version }}
RELEASE_SHA: ${{ github.sha }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag --annotate "$RELEASE_TAG" "$RELEASE_SHA" \
--message "LabKit MATLAB Workbench ${RELEASE_TAG}"
mkdir -p "artifacts/release/${RELEASE_TAG}"
git show "${RELEASE_TAG}:labkit_launcher.m" \
> "artifacts/release/${RELEASE_TAG}/labkit_launcher.m"
git show "${RELEASE_TAG}:labkit_launcher.m" \
| sha256sum \
> "artifacts/release/${RELEASE_TAG}/tag-blob.sha256"
sha256sum "artifacts/release/${RELEASE_TAG}/labkit_launcher.m" \
> "artifacts/release/${RELEASE_TAG}/asset.sha256"
diff \
<(cut -d' ' -f1 "artifacts/release/${RELEASE_TAG}/tag-blob.sha256") \
<(cut -d' ' -f1 "artifacts/release/${RELEASE_TAG}/asset.sha256")
- name: Push validated tag
env:
RELEASE_TAG: ${{ needs.validate-request.outputs.version }}
run: git push origin "refs/tags/${RELEASE_TAG}"
- name: Create draft release with verified tag asset
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.validate-request.outputs.version }}
run: |
asset="artifacts/release/${RELEASE_TAG}/labkit_launcher.m"
gh release create "$RELEASE_TAG" \
"${asset}#labkit_launcher.m" \
--repo "$GITHUB_REPOSITORY" \
--verify-tag \
--title "V${RELEASE_TAG#v}" \
--notes-file .github/RELEASE_NOTES_TEMPLATE.md \
--draft
local_digest="sha256:$(cut -d' ' -f1 \
"artifacts/release/${RELEASE_TAG}/asset.sha256")"
local_size="$(wc -c < "$asset" | tr -d '[:space:]')"
remote_digest="$(gh release view "$RELEASE_TAG" \
--repo "$GITHUB_REPOSITORY" \
--json assets \
--jq '.assets[] | select(.name == "labkit_launcher.m") | .digest')"
remote_size="$(gh release view "$RELEASE_TAG" \
--repo "$GITHUB_REPOSITORY" \
--json assets \
--jq '.assets[] | select(.name == "labkit_launcher.m") | .size')"
if [[ "$remote_digest" != "$local_digest" ]]; then
echo "::error::Remote launcher digest does not match the tag blob."
exit 1
fi
if [[ "$remote_size" != "$local_size" ]]; then
echo "::error::Remote launcher byte count does not match the tag blob."
exit 1
fi
echo "Rewrite the release notes for users, then review the asset and validation evidence before publishing the draft." \
>> "$GITHUB_STEP_SUMMARY"