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}"
0 commit comments