Skip to content

Commit 6d95368

Browse files
authored
feat(ci): add publish-chart workflow (#10)
* feat(ci): add publish-chart workflow * chore: use ubuntu-2404-2core runner * chore: wait for release and use forked trivy * fix: skip empty git commit when index is up to date * fix: correct git push logic and use env vars in publish-chart workflow * fix: improve publish-chart workflow reliability and security * chore: clarify input descriptions * fix: fail on duplicate chart publish * chore: use HELM_CHARTS_DEPLOY_TOKEN for gh-pages push * fix: skip publish if chart version already released * chore: explicitly set persist-credentials * feat: make publish-chart workflow reusable across repositories * fix: use GITHUB_TOKEN for read-only steps in publish-chart workflow * chore: cleanup publish-chart workflow * chore: add newline
1 parent 4260a8b commit 6d95368

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: Publish Helm chart
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
repository:
7+
description: 'Repository with the Helm chart (e.g. {owner}/trivy)'
8+
required: true
9+
type: string
10+
ref:
11+
description: 'Ref to checkout from the repository (e.g. commit SHA or tag)'
12+
required: true
13+
type: string
14+
chart_dir:
15+
description: 'Path to the Helm chart directory in the repository'
16+
required: true
17+
type: string
18+
19+
# Disable all GITHUB_TOKEN permissions by default; individual jobs override as needed
20+
permissions: {}
21+
22+
env:
23+
HELM_REPO: helm-charts
24+
25+
jobs:
26+
check-published:
27+
runs-on: ubuntu-2404-2core
28+
permissions:
29+
contents: read # required to read Chart.yaml and releases from public repositories via gh CLI
30+
outputs:
31+
skip: ${{ steps.check.outputs.skip }}
32+
tag: ${{ steps.check.outputs.tag }}
33+
steps:
34+
- name: Check if already published
35+
id: check
36+
env:
37+
GH_TOKEN: ${{ github.token }}
38+
REPOSITORY: ${{ inputs.repository }}
39+
CHART_DIR: ${{ inputs.chart_dir }}
40+
REF: ${{ inputs.ref }}
41+
run: |
42+
content=$(gh api "repos/$REPOSITORY/contents/$CHART_DIR/Chart.yaml?ref=$REF" \
43+
--jq '.content' | base64 -d)
44+
name=$(echo "$content" | grep '^name:' | awk '{print $2}')
45+
version=$(echo "$content" | grep '^version:' | awk '{print $2}')
46+
tag="${name}-${version}"
47+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
48+
49+
if gh release view "$tag" --repo "$GITHUB_REPOSITORY_OWNER/$HELM_REPO" > /dev/null 2>&1; then
50+
echo "Chart $tag is already published, skipping"
51+
echo "skip=true" >> "$GITHUB_OUTPUT"
52+
fi
53+
54+
publish-chart:
55+
needs: check-published
56+
if: needs.check-published.outputs.skip != 'true'
57+
runs-on: ubuntu-2404-2core
58+
permissions:
59+
contents: read # required by github.token to read releases from public repositories via gh CLI
60+
steps:
61+
- name: Checkout repository with the Helm chart
62+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
63+
with:
64+
repository: ${{ inputs.repository }}
65+
ref: ${{ inputs.ref }}
66+
persist-credentials: false
67+
sparse-checkout: ${{ inputs.chart_dir }}
68+
69+
- name: Install chart-releaser
70+
env:
71+
CR_VERSION: "1.3.0"
72+
run: |
73+
curl -sSLO "https://github.com/helm/chart-releaser/releases/download/v${CR_VERSION}/chart-releaser_${CR_VERSION}_linux_amd64.tar.gz"
74+
echo "baed2315a9bb799efb71d512c5198a2a3b8dcd139d7f22f878777cffcd649a37 chart-releaser_${CR_VERSION}_linux_amd64.tar.gz" | sha256sum -c -
75+
tar xzf "chart-releaser_${CR_VERSION}_linux_amd64.tar.gz" cr
76+
mv cr /usr/local/bin/cr
77+
rm "chart-releaser_${CR_VERSION}_linux_amd64.tar.gz"
78+
79+
- name: Package helm chart
80+
env:
81+
CHART_DIR: ${{ inputs.chart_dir }}
82+
run: |
83+
cr package "$CHART_DIR"
84+
85+
- name: Upload helm chart
86+
env:
87+
GH_TOKEN: ${{ secrets.HELM_CHARTS_DEPLOY_TOKEN }}
88+
run: |
89+
cr upload --owner "$GITHUB_REPOSITORY_OWNER" \
90+
--git-repo "$HELM_REPO" \
91+
--token "$GH_TOKEN" \
92+
--package-path .cr-release-packages
93+
94+
- name: Wait for release to be available
95+
env:
96+
GH_TOKEN: ${{ github.token }}
97+
CHART_TAG: ${{ needs.check-published.outputs.tag }}
98+
run: |
99+
# cr index fails if the release is not yet available via GitHub API
100+
# due to a race condition after cr upload creates the release
101+
max_attempts=10
102+
for i in $(seq 1 "$max_attempts"); do
103+
gh api "repos/$GITHUB_REPOSITORY_OWNER/$HELM_REPO/releases/tags/$CHART_TAG" > /dev/null && break
104+
if [[ $i -eq $max_attempts ]]; then
105+
echo "Release $CHART_TAG not available after $max_attempts attempts" >&2
106+
exit 1
107+
fi
108+
sleep 2
109+
done
110+
111+
- name: Index helm chart
112+
run: |
113+
cr index --owner "$GITHUB_REPOSITORY_OWNER" \
114+
--git-repo "$HELM_REPO" \
115+
-c "https://$GITHUB_REPOSITORY_OWNER.github.io/$HELM_REPO/" \
116+
--index-path index.yaml
117+
118+
- name: Checkout gh-pages
119+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
120+
with: # zizmor: ignore[artipacked] -- token is required to push to gh-pages
121+
ref: gh-pages
122+
path: gh-pages
123+
token: ${{ secrets.HELM_CHARTS_DEPLOY_TOKEN }}
124+
persist-credentials: true
125+
126+
- name: Push index file
127+
env:
128+
CHART_TAG: ${{ needs.check-published.outputs.tag }}
129+
run: |
130+
cp index.yaml gh-pages/index.yaml
131+
cd gh-pages
132+
git config user.email aqua-bot@users.noreply.github.com
133+
git config user.name aqua-bot
134+
git add index.yaml
135+
git commit -m "Update index.yaml for ${CHART_TAG}"
136+
git push

0 commit comments

Comments
 (0)