Skip to content

Commit fb7e38f

Browse files
feat: implement automated release workflow with image promotion polling
1 parent 953032b commit fb7e38f

2 files changed

Lines changed: 137 additions & 9 deletions

File tree

.github/workflows/release.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: Release Automation
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
id-token: write # Required for Google Auth
12+
13+
jobs:
14+
promote-and-wait:
15+
name: Promote Images and Wait for PR
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 360 # 6-hour limit for long k8s.io merge cycles
18+
outputs:
19+
pr_url: ${{ steps.extract-pr.outputs.pr_url }}
20+
21+
steps:
22+
- name: Checkout agent-sandbox
23+
uses: actions/checkout@v4
24+
with:
25+
fetch-depth: 0
26+
27+
- name: Set up Go
28+
uses: actions/setup-go@v5
29+
with:
30+
go-version-file: 'go.mod'
31+
32+
- name: Clone k8s.io
33+
env:
34+
GH_TOKEN: ${{ secrets.K8S_IO_PAT }}
35+
run: |
36+
cd ..
37+
git clone https://github.com/kubernetes/k8s.io.git
38+
cd k8s.io
39+
git remote rename origin upstream
40+
gh repo fork --clone=false || true # Ignore if already exists or fails to add remote if already there
41+
# Ensure origin remote points to the fork
42+
GH_USER=$(gh api user --jq .login)
43+
git remote add origin https://x-access-token:${{ secrets.K8S_IO_PAT }}@github.com/$GH_USER/k8s.io.git || git remote set-url origin https://x-access-token:${{ secrets.K8S_IO_PAT }}@github.com/$GH_USER/k8s.io.git
44+
45+
- name: Authenticate to Google Cloud
46+
uses: google-github-actions/auth@v2
47+
with:
48+
workload_identity_provider: '${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}'
49+
service_account: '${{ secrets.GCP_SERVICE_ACCOUNT }}'
50+
51+
- name: Set up Cloud SDK
52+
uses: google-github-actions/setup-gcloud@v2
53+
54+
- name: Setup Git Identity
55+
run: |
56+
# Use the standard GitHub Actions Bot identity
57+
git config --global user.name "github-actions[bot]"
58+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
59+
60+
- name: Run Promotion Script
61+
id: extract-pr
62+
env:
63+
# Use a PAT with permissions to fork/PR kubernetes/k8s.io
64+
GH_TOKEN: ${{ secrets.K8S_IO_PAT }}
65+
run: |
66+
# Capture output to find the PR URL directly
67+
make release-promote TAG="${GITHUB_REF_NAME}" K8S_IO_DIR=../k8s.io | tee promote_output.log
68+
69+
# Extract the URL from the log
70+
PR_URL=$(grep -o 'https://github.com/kubernetes/k8s.io/pull/[0-9]*' promote_output.log | head -n 1)
71+
72+
if [ -z "$PR_URL" ]; then
73+
echo "❌ No PR URL found in logs. Check make release-promote output."
74+
exit 1
75+
fi
76+
77+
echo "Found PR: $PR_URL"
78+
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
79+
80+
- name: Poll PR Status
81+
env:
82+
GH_TOKEN: ${{ secrets.K8S_IO_PAT }}
83+
run: |
84+
PR_URL="${{ steps.extract-pr.outputs.pr_url }}"
85+
echo "Waiting for $PR_URL to be merged..."
86+
87+
# 60 attempts, every 5 minutes = 5 hours total
88+
for i in {1..60}; do
89+
# Explicitly check the kubernetes/k8s.io repo context
90+
STATE=$(gh pr view "$PR_URL" --repo kubernetes/k8s.io --json state --jq '.state')
91+
92+
echo "Attempt $i: PR is currently $STATE"
93+
94+
if [ "$STATE" == "MERGED" ]; then
95+
echo "✅ PR merged. Proceeding."
96+
exit 0
97+
elif [ "$STATE" == "CLOSED" ]; then
98+
echo "❌ PR was closed without merging."
99+
exit 1
100+
fi
101+
102+
sleep 300
103+
done
104+
105+
echo "❌ Timed out waiting for merge."
106+
exit 1
107+
108+
publish-draft:
109+
name: Publish Draft Release
110+
needs: promote-and-wait
111+
runs-on: ubuntu-latest
112+
environment:
113+
name: agent-sandbox-release
114+
115+
steps:
116+
- name: Checkout
117+
uses: actions/checkout@v4
118+
119+
- name: Set up Go
120+
uses: actions/setup-go@v5
121+
with:
122+
go-version-file: 'go.mod'
123+
124+
- name: Set up Python
125+
uses: actions/setup-python@v5
126+
with:
127+
python-version: '3.10'
128+
129+
- name: Generate Draft Release and Manifests
130+
env:
131+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
132+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
133+
run: |
134+
# This finally publishes the draft for your review
135+
make release-publish TAG="${GITHUB_REF_NAME}"

dev/tools/tag-promote-images

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,10 @@ def main():
9595

9696
# --- Pre-flight Check ---
9797
check_local_repo_state(REMOTE_UPSTREAM)
98-
check_tag_exists(tag, remote=REMOTE_UPSTREAM)
9998

100-
# --- Step 1: Create and Push Tag ---
101-
print(f"--- Step 1: Handling Git Tag {tag} and Publish to PyPI---")
102-
create_and_push_tag(tag, remote=REMOTE_UPSTREAM)
103-
104-
print("✅ Done! The 'pypi-publish' GitHub Action should now be running.")
105-
106-
# --- Step 2: Wait for Staging Images ---
99+
# --- Step 1: Wait for Staging Images ---
107100
# CI job: https://prow.k8s.io/job-history/gs/kubernetes-ci-logs/logs/post-agent-sandbox-push-images
108-
print(f"--- Step 2: Waiting for Staging Images ---")
101+
print(f"--- Step 1: Waiting for Staging Images ---")
109102
print("⏳ Polling registry (timeout: 45 mins)...")
110103

111104
collected_digests = {}

0 commit comments

Comments
 (0)