-
Notifications
You must be signed in to change notification settings - Fork 0
137 lines (131 loc) · 5.86 KB
/
Copy pathrelease.yml
File metadata and controls
137 lines (131 loc) · 5.86 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
---
name: Release
# One repo version, two artifacts: a vX.Y.Z tag releases the `decdn.node` Ansible
# collection and the `decdn-node` Helm chart together. See RELEASING.md.
#
# `build` always runs: it gates the tag (collection, chart and both changelogs must
# agree on X.Y.Z), re-runs the chart and collection checks, packages both, and
# uploads them with SHA256SUMS as a workflow artifact. `publish` makes them public
# (Galaxy, oci://ghcr.io/decdn/charts with a keyless cosign signature, and a GitHub
# Release) ONLY when the repository variable PUBLISH_ENABLED is 'true'. Until then
# a tag push is a dry run. A manual dispatch is always a dry run.
on:
push:
tags: ['v[0-9]+.[0-9]+.[0-9]+']
workflow_dispatch:
inputs:
tag:
description: Version to dry-run, e.g. v0.1.0 (nothing is published)
required: true
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false # never cut a half-published release short
env:
TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }}
CHART_REGISTRY: oci://ghcr.io/decdn/charts
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Gate the tag against the collection, the chart and both changelogs
run: scripts/check-release-version.sh "$TAG" --notes release-notes.md
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.12'
# Helm is pinned four times: ci.yml's helm and kics jobs, and both jobs here.
# Bump all four together.
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: v4.3.0
- name: Install collection build + import tooling
run: python -m pip install --upgrade ansible-core ansible-lint galaxy-importer
- name: Build and validate the decdn.node collection
working-directory: ansible
env:
ANSIBLE_COLLECTIONS_PATH: collections
run: |
make deps
make galaxy-check
- name: Chart lint and render tests
run: make lint-helm
- name: Package the chart and write checksums
run: |
mkdir -p dist
cp ansible/build/decdn-node-*.tar.gz dist/
helm package charts/decdn-node --destination dist
(cd dist && sha256sum -- * > SHA256SUMS)
cp release-notes.md dist/
cat dist/SHA256SUMS
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-${{ env.TAG }}
path: dist/
if-no-files-found: error
publish:
needs: build
if: vars.PUBLISH_ENABLED == 'true' && github.event_name == 'push'
runs-on: ubuntu-latest
timeout-minutes: 20
# Protect this environment with required reviewers in the repository settings.
environment: release
permissions:
contents: write # the GitHub Release
packages: write # the chart on ghcr.io
id-token: write # keyless cosign signature (Sigstore)
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-${{ env.TAG }}
path: dist
- name: Verify the artifacts are the ones build checksummed
working-directory: dist
run: sha256sum --check SHA256SUMS
- name: Require the Galaxy API key
env:
GALAXY_API_KEY: ${{ secrets.GALAXY_API_KEY }}
run: |
[ -n "$GALAXY_API_KEY" ] || { echo "::error::secret GALAXY_API_KEY is not set"; exit 1; }
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: v4.3.0
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Push and sign the chart
env:
GH_TOKEN: ${{ github.token }}
run: |
# Helm and cosign keep separate credential stores (Helm's registry config
# vs Docker's config.json), so log both in: cosign pushes the signature.
echo "$GH_TOKEN" | helm registry login ghcr.io --username "$GITHUB_ACTOR" --password-stdin
echo "$GH_TOKEN" | cosign login ghcr.io --username "$GITHUB_ACTOR" --password-stdin
# Capture and print on both paths: under `bash -e` a bare out="$(…)" would
# exit on failure before the error text was shown.
if ! out="$(helm push dist/decdn-node-"${TAG#v}".tgz "$CHART_REGISTRY" 2>&1)"; then
echo "$out"
echo "::error::helm push failed"
exit 1
fi
echo "$out"
digest="$(sed -nE 's/^Digest: (sha256:[0-9a-f]{64})$/\1/p' <<<"$out")"
[ -n "$digest" ] || { echo "::error::no digest in helm push output"; exit 1; }
cosign sign --yes "ghcr.io/decdn/charts/decdn-node@$digest"
echo "chart: ${CHART_REGISTRY}/decdn-node:${TAG#v} ($digest)" >> "$GITHUB_STEP_SUMMARY"
- name: Install ansible-core
run: python3 -m pip install --upgrade ansible-core
# Not idempotent: Galaxy refuses a version that already exists, so a re-run
# after this step succeeded fails here. RELEASING.md covers recovery.
- name: Publish the collection to Galaxy
env:
GALAXY_API_KEY: ${{ secrets.GALAXY_API_KEY }}
run: ansible-galaxy collection publish dist/decdn-node-"${TAG#v}".tar.gz --api-key "$GALAXY_API_KEY"
# Last, so the Release page only appears once both artifacts are live.
- name: Create the GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --title "$TAG" \
--notes-file dist/release-notes.md \
dist/decdn-node-*.tar.gz dist/decdn-node-*.tgz dist/SHA256SUMS