-
Notifications
You must be signed in to change notification settings - Fork 2
143 lines (131 loc) · 6.05 KB
/
Copy pathobs-pr-cleanup.yml
File metadata and controls
143 lines (131 loc) · 6.05 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
name: OBS PR Cleanup
# When a PR is closed:
# - merged release PR (all changed root/** files under root/*/releases/):
# create the release tag on the merge commit and dispatch obs-release.yml
# with it (workflow_dispatch works with GITHUB_TOKEN; a tag push would
# not trigger anything — GitHub suppresses workflow-to-workflow triggers
# for the default token, and this repo has no PAT).
# - every PR: delete the PR-specific OBS project created by
# obs-pr-check.yml (no-op if it never existed) and the PR's Actions caches.
on:
pull_request:
branches: [main]
paths: ['root/**']
types: [closed]
jobs:
cleanup:
name: percona-obs sync delete pr-${{ github.event.number }}
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/obs-tools:latest
permissions:
# Required to create release tags on the merge commit.
contents: write
# Required to dispatch obs-release.yml and delete the PR's Actions caches.
actions: write
packages: read
env:
PR_NUMBER: ${{ github.event.number }}
OBS_APIURL: ${{ vars.OBS_APIURL }}
OBS_PR_ROOTPRJ: ${{ vars.OBS_PR_ROOTPRJ }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ./.github/actions/obs-setup
with:
obs-apiurl: ${{ vars.OBS_APIURL }}
obs-user: ${{ vars.OBS_USER }}
obs-password: ${{ secrets.OBS_PASSWORD }}
# Create the pr-N profile so subsequent steps can use -P "pr-N" instead
# of repeating -A and -R.
- name: Create percona-obs profiles
run: |
PR_ROOTPRJ="${OBS_PR_ROOTPRJ}:pr-${PR_NUMBER}"
venv/bin/python -m percona_obs \
-A "$OBS_APIURL" \
-R "$PR_ROOTPRJ" \
-e "REMOTE_OBS_ORG_INTERCONNECT:" \
-e "PERCONA_OBS_PACKAGING_BRANCH:refs/pull/${PR_NUMBER}/head" \
-e "PERCONA_OBS_PACKAGING_REPO:${{ github.event.pull_request.head.repo.clone_url }}" \
profile create "pr-${PR_NUMBER}"
# Detect whether this is a release-only PR (all changed root/** files are
# under root/*/releases/). This output gates tag creation below; it also
# still tells us that a release-only PR never created a PR OBS project,
# so the delete step below runs as a no-op for it.
- name: Detect release-only PR
id: detect
env:
GH_TOKEN: ${{ github.token }}
run: |
ALL_ROOT=$(gh pr view "$PR_NUMBER" \
--json files \
--jq '[.files[] | select(.path | startswith("root/")) | .path] | length')
REL_ROOT=$(gh pr view "$PR_NUMBER" \
--json files \
--jq '[.files[] | select(.path | test("^root/[^/]+/releases/")) | .path] | length')
if [ "$ALL_ROOT" -gt 0 ] && [ "$ALL_ROOT" -eq "$REL_ROOT" ]; then
echo "is_release_pr=true" >> "$GITHUB_OUTPUT"
else
echo "is_release_pr=false" >> "$GITHUB_OUTPUT"
fi
# Merged release PR: tag the merge commit (the exact reviewed snapshot)
# and dispatch the release workflow with it. Tag-creation errors other
# than "already exists" fail the job loudly — a silently missing tag is
# how releases used to vanish.
- name: Tag release and dispatch obs-release
if: github.event.pull_request.merged == true && steps.detect.outputs.is_release_pr == 'true'
env:
GH_TOKEN: ${{ github.token }}
MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
run: |
set -euo pipefail
FILES=$(gh pr view "$PR_NUMBER" --json files \
--jq '.files[].path | select(test("^root/[^/]+/releases/[^/]+/release\\.yaml$"))' | sort -u)
[ -z "$FILES" ] && { echo "No release.yaml changed; nothing to tag."; exit 0; }
while IFS= read -r release_file; do
TAG=$(git show "${MERGE_SHA}:${release_file}" | venv/bin/python3 -c \
"import sys,yaml; d=yaml.safe_load(sys.stdin); r=d.get('releases') or []; print(r[-1] if r else d.get('revision') or '')")
[ -z "$TAG" ] && continue
echo "Creating tag ${TAG} at ${MERGE_SHA}"
if ! OUT=$(gh api "repos/${GITHUB_REPOSITORY}/git/refs" -X POST \
-f "ref=refs/tags/${TAG}" -f "sha=${MERGE_SHA}" 2>&1); then
if echo "$OUT" | grep -q "Reference already exists"; then
echo "Tag ${TAG} already exists — dispatching anyway"
else
echo "::error::Failed to create tag ${TAG}: ${OUT}"
exit 1
fi
fi
echo "Dispatching obs-release.yml with tag=${TAG}"
gh workflow run obs-release.yml --ref main -f "tag=${TAG}"
done <<< "$FILES"
# Delete the PR's root project and all its sub-projects.
# --yes skips the confirmation prompt.
# --recursive ensures OBS deletes projects that still contain packages
# (e.g. if a build was in progress when the PR was closed).
# 404 responses are handled gracefully by percona-obs (no error).
- name: Delete PR OBS project
run: |
venv/bin/python -m percona_obs --verbose \
-P "pr-${PR_NUMBER}" \
sync delete \
--yes \
--recursive \
--from-obs
# Delete this PR's Actions caches (created by obs-pr-check.yml on the
# refs/pull/N/merge ref). Caches on PR merge refs can never be
# restored by main-branch runs, so leaving them around only churns the
# repo's 10 GB cache quota and evicts the main branch's caches.
- name: Delete PR Actions caches
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api --paginate \
"repos/${GITHUB_REPOSITORY}/actions/caches?ref=refs/pull/${PR_NUMBER}/merge" \
--jq '.actions_caches[].id' |
while read -r cache_id; do
echo "Deleting Actions cache id ${cache_id}"
gh api -X DELETE \
"repos/${GITHUB_REPOSITORY}/actions/caches/${cache_id}" || true
done