-
Notifications
You must be signed in to change notification settings - Fork 0
120 lines (109 loc) · 5.51 KB
/
Copy pathupstream-check.yml
File metadata and controls
120 lines (109 loc) · 5.51 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
name: Check upstream version
on:
schedule:
- cron: "33 14 * * 3" # weekly, Wednesday ~14:33 UTC — stagger minutes/day per repo to avoid a stampede
workflow_dispatch: {}
permissions:
contents: write
pull-requests: write
jobs:
check-upstream:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Read UPSTREAM.yml
id: manifest
run: |
repo=$(yq '.upstream_repo' UPSTREAM.yml)
strategy=$(yq '.version_strategy' UPSTREAM.yml)
echo "repo=$repo" >> "$GITHUB_OUTPUT"
echo "strategy=$strategy" >> "$GITHUB_OUTPUT"
- name: Get latest upstream version
id: latest
env:
GH_TOKEN: ${{ github.token }}
run: |
repo="${{ steps.manifest.outputs.repo }}"
strategy="${{ steps.manifest.outputs.strategy }}"
if [ "$strategy" = "release" ]; then
tag=$(gh api "repos/$repo/releases/latest" --jq '.tag_name')
else
tag=$(gh api "repos/$repo/tags" --jq '.[0].name')
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Compare against pinned tags
id: diff
run: |
latest="${{ steps.latest.outputs.tag }}"
changed=0
baseline=""
count=$(yq '.pinned | length' UPSTREAM.yml)
for i in $(seq 0 $((count - 1))); do
file=$(yq ".pinned[$i].file" UPSTREAM.yml)
kind=$(yq ".pinned[$i].kind" UPSTREAM.yml)
case "$kind" in
from_tag)
current=$(grep -oP '(?<=:)[^\s]+$' <(grep '^FROM' "$file" | tail -1))
[ -z "$baseline" ] && baseline="$current"
[ "$current" = "$latest" ] || { sed -i "s|:$current|:$latest|" "$file"; changed=1; }
;;
build_arg)
argname=$(yq ".pinned[$i].arg_name" UPSTREAM.yml)
current=$(grep -oP "(?<=^ARG ${argname}=)[^\s]+$" "$file")
[ -z "$baseline" ] && baseline="$current"
[ "$current" = "$latest" ] || { sed -i "s|ARG ${argname}=${current}|ARG ${argname}=${latest}|" "$file"; changed=1; }
;;
digest)
# Intentionally not auto-bumped: no upstream version tag to compare against.
# Flagged in the PR body as a manual-check reminder instead.
;;
*)
echo "::warning::unknown pin kind '$kind' for $file, skipping" ;;
esac
done
echo "changed=$changed" >> "$GITHUB_OUTPUT"
echo "latest=$latest" >> "$GITHUB_OUTPUT"
echo "baseline=$baseline" >> "$GITHUB_OUTPUT"
- name: Classify bump size
id: bump
run: |
strip() { echo "$1" | grep -oP '\d+(\.\d+){0,2}' | head -1; }
old_major=$(strip "${{ steps.diff.outputs.baseline }}" | cut -d. -f1)
new_major=$(strip "${{ steps.diff.outputs.latest }}" | cut -d. -f1)
if [ -n "$old_major" ] && [ -n "$new_major" ] && [ "$old_major" != "$new_major" ]; then
echo "major=1" >> "$GITHUB_OUTPUT"
else
echo "major=0" >> "$GITHUB_OUTPUT"
fi
- name: Ensure major-version-bump label exists
if: steps.diff.outputs.changed == '1' && steps.bump.outputs.major == '1'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh label create major-version-bump --color B60205 --description "Upstream cut a major release — review breaking changes before merging" 2>/dev/null || true
- name: Open PR
if: steps.diff.outputs.changed == '1'
env:
GH_TOKEN: ${{ github.token }}
run: |
branch="upstream-bump/${{ steps.diff.outputs.latest }}"
git checkout -b "$branch"
git config user.name "template-factory-bot"
git config user.email "actions@users.noreply.github.com"
git add -A
git commit -m "chore: bump upstream to ${{ steps.diff.outputs.latest }}"
git push -u origin "$branch"
digest_note=""
if yq -e '.pinned[] | select(.kind == "digest")' UPSTREAM.yml > /dev/null 2>&1; then
digest_note=$'\n\n**Note:** one or more services pin by image digest, not version tag (no upstream version exists to compare) — those were *not* touched by this bump and still need a manual check if you want the latest image.'
fi
title="Bump upstream to ${{ steps.diff.outputs.latest }}"
major_note=""
if [ "${{ steps.bump.outputs.major }}" = "1" ]; then
title="[MAJOR] $title"
major_note=$'\n\n**⚠️ Major version bump** ('"${{ steps.diff.outputs.baseline }}"' → '"${{ steps.diff.outputs.latest }}"$'). Treat this like a new integration, not a routine patch:\n- Re-read the upstream changelog/migration guide for breaking changes (env vars, config shape, DB migrations)\n- Diff against `docs/railway-wiring.md` — service graph, required vars, or volumes may have changed\n- Re-run local `docker compose up` sanity + a smoke deploy before merging; do not fast-merge on CI green alone'
fi
gh pr create --title "$title" \
--body "Automated version check found a newer upstream release. Review the [upstream changelog](https://github.com/${{ steps.manifest.outputs.repo }}/releases/tag/${{ steps.diff.outputs.latest }}) before merging — this does not run a smoke deploy.${major_note}${digest_note}" \
--head "$branch" \
$([ "${{ steps.bump.outputs.major }}" = "1" ] && echo "--label major-version-bump")