Skip to content

Commit dfd8aba

Browse files
workflow to update the images
1 parent cab6533 commit dfd8aba

File tree

3 files changed

+457
-18
lines changed

3 files changed

+457
-18
lines changed
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
name: Phase 3 - Update Operator with SHA256 Digests
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
phase2_run_id:
7+
description: 'Phase 2 workflow run ID (from sumologic-openshift-images repo)'
8+
required: true
9+
type: string
10+
helm_chart_version:
11+
description: 'Helm chart version (e.g., 4.18.0)'
12+
required: true
13+
type: string
14+
branch_name:
15+
description: 'Branch name for PR (optional, default: prepare_{version})'
16+
required: false
17+
type: string
18+
default: ''
19+
20+
defaults:
21+
run:
22+
shell: bash
23+
24+
jobs:
25+
update-operator:
26+
runs-on: ubuntu-22.04
27+
28+
steps:
29+
- name: Checkout Operator Repository
30+
uses: actions/checkout@v4
31+
with:
32+
repository: SumoLogic/sumologic-kubernetes-collection-helm-operator
33+
token: ${{ secrets.GITHUB_TOKEN }}
34+
submodules: true
35+
36+
- name: Setup Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: '3.11'
40+
41+
- name: Install Dependencies
42+
run: |
43+
pip install pyyaml
44+
sudo apt-get update && sudo apt-get install -y jq
45+
46+
- name: Download Phase 2 Artifact
47+
uses: actions/download-artifact@v4
48+
with:
49+
name: certified-images
50+
run-id: ${{ inputs.phase2_run_id }}
51+
github-token: ${{ secrets.GITHUB_TOKEN }}
52+
repository: SumoLogic/sumologic-openshift-images
53+
54+
- name: Verify Certified Images
55+
id: verify
56+
run: |
57+
if [ ! -f certified_images.json ]; then
58+
echo "❌ certified_images.json not found"
59+
exit 1
60+
fi
61+
62+
SUCCESS_COUNT=$(jq '[.certified_images[] | select(.certification_status == "success")] | length' certified_images.json)
63+
TOTAL_COUNT=$(jq '.certified_images | length' certified_images.json)
64+
65+
echo "Total images: ${TOTAL_COUNT}, Successful: ${SUCCESS_COUNT}"
66+
67+
if [ "${SUCCESS_COUNT}" -eq 0 ]; then
68+
echo "❌ No successfully certified images found"
69+
exit 1
70+
fi
71+
72+
echo "success_count=${SUCCESS_COUNT}" >> $GITHUB_OUTPUT
73+
echo "total_count=${TOTAL_COUNT}" >> $GITHUB_OUTPUT
74+
75+
- name: Convert Certified Images to Update Script Format
76+
run: |
77+
python3 scripts/convert_certified_images.py \
78+
--input certified_images.json \
79+
--output images.txt
80+
echo "Generated images.txt with $(wc -l < images.txt) entries"
81+
82+
- name: Create Branch
83+
id: branch
84+
run: |
85+
BRANCH="${{ inputs.branch_name }}"
86+
if [ -z "${BRANCH}" ]; then
87+
BRANCH="prepare_${{ inputs.helm_chart_version }}"
88+
fi
89+
90+
git config user.name "github-actions[bot]"
91+
git config user.email "github-actions[bot]@users.noreply.github.com"
92+
git checkout -b "${BRANCH}"
93+
94+
echo "branch=${BRANCH}" >> $GITHUB_OUTPUT
95+
96+
- name: Update Component Images
97+
run: |
98+
python3 scripts/update_images.py \
99+
--images-file images.txt \
100+
--operator-repo-dir ./ \
101+
--create-new-file True
102+
103+
- name: Verify Generated Files
104+
run: |
105+
FILES=(
106+
"bundle/manifests/operator.clusterserviceversion_new.yaml"
107+
"config/manager/manager_new.yaml"
108+
"tests/replace_components_images_new.sh"
109+
"tests/helm_install_new.sh"
110+
)
111+
112+
for file in "${FILES[@]}"; do
113+
if [ ! -f "${file}" ]; then
114+
echo "❌ ${file} not found"
115+
exit 1
116+
fi
117+
done
118+
echo "All files generated successfully"
119+
120+
- name: Replace Old Files with New Versions
121+
run: |
122+
mv bundle/manifests/operator.clusterserviceversion_new.yaml \
123+
bundle/manifests/operator.clusterserviceversion.yaml
124+
mv config/manager/manager_new.yaml \
125+
config/manager/manager.yaml
126+
mv tests/replace_components_images_new.sh \
127+
tests/replace_components_images.sh
128+
mv tests/helm_install_new.sh \
129+
tests/helm_install.sh
130+
chmod +x tests/helm_install.sh tests/replace_components_images.sh
131+
132+
- name: Update Helm Chart Version in Test Scripts
133+
run: sed -i "s/--version [0-9]\+\.[0-9]\+\.[0-9]\+/--version ${{ inputs.helm_chart_version }}/g" tests/helm_install.sh
134+
135+
- name: Update Helm Submodule
136+
run: |
137+
cd helm-charts/sumologic-kubernetes-collection
138+
git fetch --tags origin
139+
140+
if ! git checkout "v${{ inputs.helm_chart_version }}"; then
141+
echo "❌ Failed to checkout v${{ inputs.helm_chart_version }}"
142+
git tag | grep "v${{ inputs.helm_chart_version }}" || echo "No matching tags found"
143+
exit 1
144+
fi
145+
146+
cd ../..
147+
git add helm-charts/sumologic-kubernetes-collection
148+
149+
- name: Generate watches.yaml
150+
run: |
151+
make generate-watches
152+
153+
if [ ! -f watches_new.yaml ]; then
154+
echo "❌ watches_new.yaml not generated"
155+
exit 1
156+
fi
157+
158+
if [ -f watches.yaml ] && diff -u watches.yaml watches_new.yaml > watches.diff; then
159+
rm watches_new.yaml
160+
else
161+
echo "⚠️ watches_new.yaml requires manual review"
162+
fi
163+
164+
- name: Update bundle.yaml
165+
run: |
166+
make generate-bundle
167+
168+
if [ ! -f generated_bundle.yaml ]; then
169+
echo "❌ generated_bundle.yaml not generated"
170+
exit 1
171+
fi
172+
173+
mv generated_bundle.yaml bundle.yaml
174+
175+
- name: Commit Changes
176+
run: |
177+
git add bundle/manifests/operator.clusterserviceversion.yaml \
178+
config/manager/manager.yaml \
179+
bundle.yaml \
180+
tests/replace_components_images.sh \
181+
tests/helm_install.sh \
182+
helm-charts/sumologic-kubernetes-collection
183+
184+
[ -f watches_new.yaml ] && git add watches_new.yaml
185+
186+
git commit -m "chore: update Sumologic Collection Helm Chart to ${{ inputs.helm_chart_version }}"
187+
188+
- name: Push Branch
189+
run: git push origin "${{ steps.branch.outputs.branch }}"
190+
191+
- name: Create Pull Request
192+
id: create_pr
193+
uses: actions/github-script@v7
194+
with:
195+
script: |
196+
const fs = require('fs');
197+
const watchesNewExists = fs.existsSync('watches_new.yaml');
198+
199+
const { data: pr } = await github.rest.pulls.create({
200+
owner: context.repo.owner,
201+
repo: context.repo.repo,
202+
title: `chore: update operator images to helm chart v${{ inputs.helm_chart_version }}`,
203+
head: '${{ steps.branch.outputs.branch }}',
204+
base: 'main',
205+
body: `## Update Helm Operator for v${{ inputs.helm_chart_version }}
206+
207+
Updates component images with certified SHA256 digests from OpenShift certification.
208+
209+
**Images certified:** ${{ steps.verify.outputs.success_count }} / ${{ steps.verify.outputs.total_count }}
210+
211+
### Files Updated
212+
213+
- \`config/manager/manager.yaml\`
214+
- \`bundle/manifests/operator.clusterserviceversion.yaml\`
215+
- \`bundle.yaml\`
216+
- \`tests/replace_components_images.sh\`
217+
- \`tests/helm_install.sh\`
218+
- \`helm-charts/sumologic-kubernetes-collection\` (submodule → v${{ inputs.helm_chart_version }})
219+
${watchesNewExists ? '\n⚠️ **Action Required:** Review and merge \`watches_new.yaml\` if changes are needed' : ''}
220+
221+
### Testing
222+
223+
${watchesNewExists ? `1. Review \`watches_new.yaml\` for new RELATED_IMAGE_* transformations\n2. ` : '1. '}Run \`make test && make deploy-helm-chart\`
224+
${watchesNewExists ? '3. ' : '2. '}Verify operator deployment on test cluster
225+
226+
### Automation
227+
228+
- [Phase 2 Certification](https://github.com/SumoLogic/sumologic-openshift-images/actions/runs/${{ inputs.phase2_run_id }})
229+
- [Phase 3 Update](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
230+
231+
### 📚 Related Documentation
232+
233+
- [Update Process](https://github.com/SumoLogic/sumologic-kubernetes-collection-helm-operator/blob/main/docs/dev/update.md)
234+
- [Helm Chart v${{ inputs.helm_chart_version }} Release Notes](https://github.com/SumoLogic/sumologic-kubernetes-collection/releases/tag/v${{ inputs.helm_chart_version }})
235+
236+
---
237+
238+
**Auto-generated by Phase 3 automation** 🤖
239+
`
240+
});
241+
242+
console.log(`✅ PR created: ${pr.html_url}`);
243+
return pr.number;
244+
245+
- name: Output Summary
246+
run: |
247+
echo "## ✅ Phase 3 Complete" >> $GITHUB_STEP_SUMMARY
248+
echo "" >> $GITHUB_STEP_SUMMARY
249+
echo "### 🎉 Pull Request Created Successfully" >> $GITHUB_STEP_SUMMARY
250+
echo "" >> $GITHUB_STEP_SUMMARY
251+
echo "🔗 **[View PR #${{ steps.create_pr.outputs.result }}](https://github.com/SumoLogic/sumologic-kubernetes-collection-helm-operator/pull/${{ steps.create_pr.outputs.result }})**" >> $GITHUB_STEP_SUMMARY
252+
echo "" >> $GITHUB_STEP_SUMMARY
253+
echo "**Branch:** \`${{ steps.branch.outputs.branch }}\`" >> $GITHUB_STEP_SUMMARY
254+
echo "" >> $GITHUB_STEP_SUMMARY
255+
echo "### 📊 Summary" >> $GITHUB_STEP_SUMMARY
256+
echo "" >> $GITHUB_STEP_SUMMARY
257+
echo "- **Helm Chart Version:** ${{ inputs.helm_chart_version }}" >> $GITHUB_STEP_SUMMARY
258+
echo "- **Images Updated:** ${{ steps.verify.outputs.success_count }} / ${{ steps.verify.outputs.total_count }}" >> $GITHUB_STEP_SUMMARY
259+
echo "- **Phase 2 Run:** [${{ inputs.phase2_run_id }}](https://github.com/SumoLogic/sumologic-openshift-images/actions/runs/${{ inputs.phase2_run_id }})" >> $GITHUB_STEP_SUMMARY
260+
echo "" >> $GITHUB_STEP_SUMMARY
261+
262+
if [ -f watches_new.yaml ]; then
263+
echo "### ⚠️ Manual Review Required" >> $GITHUB_STEP_SUMMARY
264+
echo "" >> $GITHUB_STEP_SUMMARY
265+
echo "Please review \`watches_new.yaml\` and merge if changes are needed." >> $GITHUB_STEP_SUMMARY
266+
echo "" >> $GITHUB_STEP_SUMMARY
267+
fi
268+
269+
echo "### 📝 Updated Files" >> $GITHUB_STEP_SUMMARY
270+
echo "" >> $GITHUB_STEP_SUMMARY
271+
echo "- ✅ \`config/manager/manager.yaml\`" >> $GITHUB_STEP_SUMMARY
272+
echo "- ✅ \`bundle/manifests/operator.clusterserviceversion.yaml\`" >> $GITHUB_STEP_SUMMARY
273+
echo "- ✅ \`bundle.yaml\`" >> $GITHUB_STEP_SUMMARY
274+
echo "- ✅ \`tests/replace_components_images.sh\`" >> $GITHUB_STEP_SUMMARY
275+
echo "- ✅ \`tests/helm_install.sh\`" >> $GITHUB_STEP_SUMMARY
276+
echo "- ✅ \`helm-charts/sumologic-kubernetes-collection\` (submodule)" >> $GITHUB_STEP_SUMMARY
277+
278+
if [ -f watches_new.yaml ]; then
279+
echo "- ⚠️ \`watches_new.yaml\` (needs review)" >> $GITHUB_STEP_SUMMARY
280+
fi
281+
282+
echo "" >> $GITHUB_STEP_SUMMARY
283+
echo "### 🚀 Next Steps" >> $GITHUB_STEP_SUMMARY
284+
echo "" >> $GITHUB_STEP_SUMMARY
285+
echo "1. Review the PR" >> $GITHUB_STEP_SUMMARY
286+
echo "2. Run tests locally" >> $GITHUB_STEP_SUMMARY
287+
echo "3. Deploy to test cluster" >> $GITHUB_STEP_SUMMARY
288+
echo "4. Merge when ready" >> $GITHUB_STEP_SUMMARY
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Converts certified_images.json from Phase 2 into the format expected by update_images.py
4+
5+
Input: certified_images.json from Phase 2
6+
Output: images.txt in the format expected by update_images.py
7+
8+
Format expected by update_images.py (pairs of lines):
9+
registry. connect.redhat.com/sumologic/fluent-bit:3.0.0-ubi
10+
registry.connect.redhat. com/sumologic/fluent-bit:@sha256:abc123...
11+
registry.connect.redhat.com/sumologic/node-exporter:v1.3.1-ubi
12+
registry.connect.redhat.com/sumologic/node-exporter: @sha256:1934ef...
13+
"""
14+
15+
import json
16+
import argparse
17+
import sys
18+
19+
20+
def convert_certified_images_to_text(json_file: str, output_file: str):
21+
"""
22+
Convert certified_images.json to text format expected by update_images.py
23+
24+
Args:
25+
json_file: Path to certified_images.json from Phase 2
26+
output_file: Path to output text file
27+
"""
28+
with open(json_file, 'r', encoding='utf-8') as f:
29+
data = json.load(f)
30+
31+
lines = []
32+
skipped = []
33+
34+
for img in data['certified_images']:
35+
# Skip failed or pending certifications
36+
if img['certification_status'] != 'success':
37+
skipped.append(f"{img['name']} - Status: {img['certification_status']}")
38+
continue
39+
40+
# Extract components
41+
name = img['name']
42+
version = img['version']
43+
sha256 = img['sha256']
44+
45+
# Validate required fields
46+
if not name or not version or not sha256:
47+
skipped.append(f"{name} - Missing required fields")
48+
continue
49+
50+
# Generate the two lines expected by update_images.py
51+
# Line 1: registry.connect.redhat.com/sumologic/{name}:{version}-ubi
52+
image_with_tag = f"registry.connect.redhat.com/sumologic/{name}:{version}-ubi"
53+
54+
# Line 2: registry.connect.redhat.com/sumologic/{name}:@{sha256}
55+
# Remove 'sha256:' prefix if present
56+
sha256_clean = sha256.replace('sha256:', '')
57+
image_with_sha = f"registry.connect.redhat.com/sumologic/{name}:@sha256:{sha256_clean}"
58+
59+
lines.append(image_with_tag)
60+
lines.append(image_with_sha)
61+
62+
# Report skipped images
63+
if skipped:
64+
print("⚠️ Skipped images:", file=sys.stderr)
65+
for skip in skipped:
66+
print(f" - {skip}", file=sys. stderr)
67+
68+
# Write to output file
69+
with open(output_file, 'w', encoding='utf-8') as f:
70+
f.write('\n'. join(lines))
71+
if lines: # Add final newline only if there's content
72+
f.write('\n')
73+
74+
print(f"✅ Converted {len(lines)//2} images to {output_file}")
75+
76+
# Return count for validation
77+
return len(lines) // 2
78+
79+
80+
def parse_args():
81+
"""Parse command line arguments"""
82+
parser = argparse.ArgumentParser(
83+
description='Convert certified_images.json to update_images.py format'
84+
)
85+
parser.add_argument(
86+
'--input',
87+
required=True,
88+
help='Path to certified_images.json'
89+
)
90+
parser.add_argument(
91+
'--output',
92+
default='images.txt',
93+
help='Path to output file (default: images.txt)'
94+
)
95+
return parser.parse_args()
96+
97+
98+
if __name__ == '__main__':
99+
args = parse_args()
100+
count = convert_certified_images_to_text(args.input, args.output)
101+
102+
if count == 0:
103+
print("❌ No images converted", file=sys.stderr)
104+
sys.exit(1)

0 commit comments

Comments
 (0)