Skip to content

Commit 90c85bc

Browse files
committed
helm-diff: port gha-tools report logic (per-scenario +/- counts, layout); minimize-outdated comments via github-script (drop marocchino); diff union of base+head scenarios
1 parent 8b54b3e commit 90c85bc

1 file changed

Lines changed: 109 additions & 36 deletions

File tree

.github/workflows/helm-diff.yaml

Lines changed: 109 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ name: Helm Render Diff
33
# Informational: renders every test-values scenario on both the PR base and head,
44
# diffs the resulting Kubernetes manifests, and posts a sticky PR comment so
55
# reviewers can see exactly what a change does to the rendered output.
6-
# Runs on GitHub-hosted runners with only public actions (public repo, no secrets
7-
# beyond the automatic GITHUB_TOKEN). Never fails the PR.
6+
#
7+
# This ports the diff/report logic from comet-ml/gha-tools helm/helm-diff, but
8+
# runs self-contained on GitHub-hosted runners with public actions — that private
9+
# action runs on the self-hosted `helm` runner and can't be used from a public
10+
# repo (fork PRs can't pull a private action, and self-hosted runners must not run
11+
# fork code). Never fails the PR (the hard gate is lint-render.yaml).
812

913
on:
1014
pull_request:
@@ -14,9 +18,14 @@ on:
1418
permissions:
1519
contents: read
1620
pull-requests: write
21+
issues: write
1722

1823
env:
1924
KUBE_VERSION: "1.29.0"
25+
CHART_PATH: charts/s3proxy
26+
# Match gha-tools helm-diff defaults so output is consistent with our other charts.
27+
RELEASE_NAME: release
28+
NAMESPACE: default
2029

2130
jobs:
2231
render-diff:
@@ -26,13 +35,13 @@ jobs:
2635
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2736
with:
2837
ref: ${{ github.event.pull_request.head.sha }}
29-
path: head
38+
path: pr-repo
3039

3140
- name: Checkout base
3241
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3342
with:
3443
ref: ${{ github.event.pull_request.base.sha }}
35-
path: base
44+
path: base-repo
3645

3746
- name: Set up Helm
3847
uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
@@ -42,74 +51,138 @@ jobs:
4251
- name: Render and diff
4352
run: |
4453
set -uo pipefail
54+
55+
# render <repo-dir> <values-relpath> <out-file>
56+
# Renders the chart if both the chart dir and the values file exist on
57+
# that side; otherwise writes an empty baseline (mirrors gha-tools, so a
58+
# values file that only exists on the PR shows up as fully added).
4559
render() {
46-
# render <repo-dir> <values-relpath> <out-file>
4760
local dir="$1" vals="$2" out="$3"
48-
if [ -f "${dir}/${vals}" ] && [ -d "${dir}/charts/s3proxy" ]
61+
if [ -f "${dir}/${vals}" ] && [ -d "${dir}/${CHART_PATH}" ]
4962
then
50-
helm template s3proxy "${dir}/charts/s3proxy" \
51-
--values "${dir}/${vals}" \
52-
--kube-version "${KUBE_VERSION}" > "$out" 2>"${out}.err" || {
53-
echo "render error for ${dir}/${vals}:"
54-
cat "${out}.err"
55-
: > "$out"
56-
}
63+
if ! helm template "${RELEASE_NAME}" "${dir}/${CHART_PATH}" \
64+
--namespace "${NAMESPACE}" \
65+
--values "${dir}/${vals}" \
66+
--kube-version "${KUBE_VERSION}" > "$out" 2>"${out}.err"
67+
then
68+
echo "⚠️ render error for ${dir}/${vals}:"
69+
cat "${out}.err"
70+
: > "$out"
71+
fi
5772
else
5873
: > "$out"
5974
fi
6075
}
6176
6277
summary=diff-summary.md
63-
echo "## 📊 Helm render diff (base vs PR)" > "$summary"
64-
echo "" >> "$summary"
65-
echo "_Rendered with Kubernetes ${KUBE_VERSION}. Informational only — this check never fails the PR._" >> "$summary"
78+
{
79+
echo "<!-- helm-render-diff -->"
80+
echo "## 📊 Helm Render Diff (base vs PR)"
81+
echo ""
82+
echo "Chart \`${CHART_PATH}\` rendered with Kubernetes \`${KUBE_VERSION}\`. Informational only — this check never fails the PR."
83+
} > "$summary"
84+
85+
# Union of scenario files across base and head, so a scenario removed in
86+
# the PR (present on base, absent on head) still shows up as a deletion.
87+
names="$(
88+
{ ls -1 pr-repo/test-values/*.yaml base-repo/test-values/*.yaml 2>/dev/null || true; } \
89+
| xargs -r -n1 basename | sort -u
90+
)"
6691
67-
changed=0
68-
for f in head/test-values/*.yaml
92+
any_changes=0
93+
while IFS= read -r name
6994
do
70-
name="$(basename "$f")"
71-
render head "test-values/${name}" "/tmp/head-${name}"
72-
render base "test-values/${name}" "/tmp/base-${name}"
73-
if ! diff -u "/tmp/base-${name}" "/tmp/head-${name}" > "/tmp/diff-${name}"
95+
[ -n "$name" ] || continue
96+
render pr-repo "test-values/${name}" "/tmp/after-${name}"
97+
render base-repo "test-values/${name}" "/tmp/before-${name}"
98+
99+
diff -u "/tmp/before-${name}" "/tmp/after-${name}" > "/tmp/diff-${name}" || true
100+
101+
if [ -s "/tmp/diff-${name}" ]
74102
then
75-
changed=1
103+
any_changes=1
104+
# Additions/deletions, excluding the +++/--- file headers (as gha-tools does).
105+
additions=$(grep '^+' "/tmp/diff-${name}" | grep -vc '^+++' || true)
106+
deletions=$(grep '^-' "/tmp/diff-${name}" | grep -vc '^---' || true)
76107
{
77108
echo ""
78-
echo "<details><summary>🔄 <code>${name}</code></summary>"
109+
echo "### \`test-values/${name}\`"
110+
echo ""
111+
echo "- **Status**: 🔄 Changes Detected"
112+
echo "- **Changes**: +${additions} -${deletions}"
113+
echo ""
114+
echo "<details><summary>🔍 Click to view complete diff</summary>"
79115
echo ""
80116
echo '```diff'
81117
cat "/tmp/diff-${name}"
82118
echo '```'
83119
echo ""
84120
echo "</details>"
85121
} >> "$summary"
122+
else
123+
{
124+
echo ""
125+
echo "### \`test-values/${name}\`"
126+
echo ""
127+
echo "- **Status**: ✅ No Changes"
128+
} >> "$summary"
86129
fi
87-
done
130+
done <<< "$names"
88131
89-
if [ "$changed" -eq 0 ]
132+
if [ "$any_changes" -eq 0 ]
90133
then
91134
echo "" >> "$summary"
92-
echo "_No rendered manifest changes across the test-values scenarios._" >> "$summary"
135+
echo "_No rendered manifest changes across any scenario._" >> "$summary"
93136
fi
94137
95-
# Always publish the full diff to the job summary.
138+
# Always publish the full report to the job summary (no size limit there).
96139
cat "$summary" >> "$GITHUB_STEP_SUMMARY"
97140
98141
# Cap the PR comment to stay well under GitHub's 65536-char limit.
99142
if [ "$(wc -c < "$summary")" -gt 60000 ]
100143
then
101144
head -c 60000 "$summary" > diff-comment.md
102-
{
103-
echo ""
104-
echo "…diff truncated — see the full render diff in the workflow job summary."
105-
} >> diff-comment.md
145+
printf '\n\n…diff truncated — see the full render diff in the workflow job summary.\n' >> diff-comment.md
106146
else
107147
cp "$summary" diff-comment.md
108148
fi
109149
110-
- name: Post sticky comment
150+
# Match the repo's preview-readme.yaml convention: minimize (collapse) any
151+
# previous render-diff comments as OUTDATED, then post a fresh one. Uses
152+
# first-party actions/github-script (no third-party comment action).
153+
# continue-on-error: fork PRs get a read-only token and cannot comment; the
154+
# full diff is still available in the job summary.
155+
- name: Minimize outdated diff comments and post the latest
111156
continue-on-error: true
112-
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
157+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
113158
with:
114-
header: helm-render-diff
115-
path: diff-comment.md
159+
script: |
160+
const fs = require('fs');
161+
const marker = '<!-- helm-render-diff -->';
162+
const body = fs.readFileSync('diff-comment.md', 'utf8');
163+
164+
const comments = await github.paginate(github.rest.issues.listComments, {
165+
owner: context.repo.owner,
166+
repo: context.repo.repo,
167+
issue_number: context.issue.number,
168+
});
169+
170+
for (const comment of comments) {
171+
if (comment.user.type === 'Bot' && comment.body.includes(marker)) {
172+
await github.graphql(
173+
`mutation($id: ID!) {
174+
minimizeComment(input: { subjectId: $id, classifier: OUTDATED }) {
175+
clientMutationId
176+
}
177+
}`,
178+
{ id: comment.node_id },
179+
);
180+
}
181+
}
182+
183+
await github.rest.issues.createComment({
184+
owner: context.repo.owner,
185+
repo: context.repo.repo,
186+
issue_number: context.issue.number,
187+
body,
188+
});

0 commit comments

Comments
 (0)