Skip to content

Commit 52158b0

Browse files
authored
Merge pull request #2460 from keboola/feat-add-revert-gh-actions-for-cli
feat: Add revert GH actions for CLI automating removing from S3 bucket and releases indexes
2 parents ed8059c + a689616 commit 52158b0

6 files changed

Lines changed: 589 additions & 6 deletions

File tree

.github/workflows/claude-code-review.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
---
12
name: Code Review - Claude
23

34
on:
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
---
2+
name: "Revert: CLI Release"
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
version:
8+
description: 'Version to revert (e.g., 1.2.3)'
9+
required: true
10+
type: string
11+
dry_run:
12+
description: 'Dry run mode (only show what would be done)'
13+
required: false
14+
type: boolean
15+
default: false
16+
17+
env:
18+
# S3 Repository in CLI Assets Account
19+
BASE_URL: "https://cli-dist.keboola.com"
20+
AWS_REGION: us-east-1
21+
AWS_BUCKET_NAME: cli-dist-keboola-com
22+
AWS_ROLE_TO_ASSUME: arn:aws:iam::455460941449:role/cli-dist-release
23+
AWS_ROLE_REGION: eu-central-1
24+
25+
jobs:
26+
validate-version:
27+
name: "Validate Version"
28+
runs-on: ubuntu-latest
29+
outputs:
30+
version: ${{ steps.version.outputs.version }}
31+
tag: ${{ steps.version.outputs.tag }}
32+
steps:
33+
- name: Validate version format
34+
id: version
35+
run: |
36+
VERSION="${{ github.event.inputs.version }}"
37+
# Validate semantic versioning format
38+
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?$ ]]; then
39+
echo "Error: Invalid version format: $VERSION"
40+
echo "Expected format: X.Y.Z or X.Y.Z-prerelease.1"
41+
exit 1
42+
fi
43+
44+
# Determine tag format (with or without 'v' prefix)
45+
TAG="v${VERSION}"
46+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
47+
echo "tag=${TAG}" >> $GITHUB_OUTPUT
48+
echo "✅ Version validated: ${VERSION} (tag: ${TAG})"
49+
50+
revert-s3:
51+
name: "Remove from S3"
52+
needs:
53+
- validate-version
54+
env:
55+
VERSION: ${{ needs.validate-version.outputs.version }}
56+
permissions:
57+
id-token: write
58+
contents: read
59+
runs-on: ubuntu-latest
60+
steps:
61+
- name: Check out the repo
62+
uses: actions/checkout@v5
63+
64+
- name: Configure AWS Credentials to CLI Assets Account
65+
uses: aws-actions/configure-aws-credentials@v5
66+
with:
67+
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }}
68+
aws-region: ${{ env.AWS_REGION }}
69+
70+
- name: Remove files from S3
71+
shell: bash
72+
env:
73+
AWS_REGION: ${{ env.AWS_REGION }}
74+
AWS_BUCKET_NAME: ${{ env.AWS_BUCKET_NAME }}
75+
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
76+
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
77+
AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }}
78+
DRY_RUN: ${{ github.event.inputs.dry_run == 'true' && 'true' || 'false' }}
79+
run: |
80+
chmod +x ./build/package/s3/unpublish.sh
81+
./build/package/s3/unpublish.sh "${{ env.VERSION }}" "$DRY_RUN"
82+
83+
reindex-linux-repos:
84+
name: "Re-index Linux Repositories"
85+
needs:
86+
- validate-version
87+
- revert-s3
88+
if: ${{ github.event.inputs.dry_run != 'true' }}
89+
env:
90+
VERSION: ${{ needs.validate-version.outputs.version }}
91+
permissions:
92+
id-token: write
93+
contents: read
94+
runs-on: ubuntu-latest
95+
steps:
96+
- name: Check out the repo
97+
uses: actions/checkout@v5
98+
99+
- name: Install GPG
100+
run: sudo apt-get update && sudo apt-get install -y gnupg
101+
102+
- name: Setup Docker Buildx
103+
uses: docker/setup-buildx-action@v3
104+
105+
- name: Docker login
106+
uses: docker/login-action@v3
107+
with:
108+
username: ${{ secrets.DOCKERHUB_USER }}
109+
password: ${{ secrets.DOCKERHUB_TOKEN }}
110+
111+
- name: Build DEB repo tools
112+
uses: ./.github/actions/build-repo-tools
113+
with:
114+
type: deb
115+
116+
- name: Build RPM repo tools
117+
uses: ./.github/actions/build-repo-tools
118+
with:
119+
type: rpm
120+
121+
- name: Build APK repo tools
122+
uses: ./.github/actions/build-repo-tools
123+
with:
124+
type: apk
125+
126+
- name: Clean aws credentials file
127+
run: rm -rf ${HOME}/.aws
128+
129+
- name: Configure AWS Credentials to CLI Assets Account
130+
uses: aws-actions/configure-aws-credentials@v5
131+
with:
132+
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }}
133+
aws-region: ${{ env.AWS_ROLE_REGION }}
134+
135+
- name: Mount CLI Assets S3 Bucket
136+
uses: ./.github/actions/mount-s3
137+
with:
138+
mountedFolder: /s3bucket
139+
awsRegion: ${{ env.AWS_REGION }}
140+
awsBucketName: ${{ env.AWS_BUCKET_NAME }}
141+
awsAccessKeyId: ${{ env.AWS_ACCESS_KEY_ID }}
142+
awsSecretAccessKey: ${{ env.AWS_SECRET_ACCESS_KEY }}
143+
awsSessionToken: ${{ env.AWS_SESSION_TOKEN }}
144+
145+
- name: Re-index Linux packages in CLI Assets S3
146+
run: ./build/package/linux/index.sh /s3bucket
147+
env:
148+
DEB_KEY_PUBLIC: ${{ secrets.DEB_KEY_PUBLIC }}
149+
RPM_KEY_PUBLIC: ${{ secrets.RPM_KEY_PUBLIC }}
150+
APK_KEY_PUBLIC: ${{ secrets.APK_KEY_PUBLIC }}
151+
DEB_KEY_PRIVATE: ${{ secrets.DEB_KEY_PRIVATE }}
152+
RPM_KEY_PRIVATE: ${{ secrets.RPM_KEY_PRIVATE }}
153+
APK_KEY_PRIVATE: ${{ secrets.APK_KEY_PRIVATE }}
154+
155+
unpublish-github-release:
156+
name: "Unpublish GitHub Release"
157+
needs:
158+
- validate-version
159+
if: ${{ github.event.inputs.dry_run != 'true' }}
160+
env:
161+
VERSION: ${{ needs.validate-version.outputs.version }}
162+
TAG: ${{ needs.validate-version.outputs.tag }}
163+
permissions:
164+
contents: write
165+
runs-on: ubuntu-latest
166+
steps:
167+
- name: Check if release exists
168+
id: check_release
169+
uses: actions/github-script@v7
170+
with:
171+
github-token: ${{ secrets.GITHUB_TOKEN }}
172+
script: |
173+
const tag = '${{ env.TAG }}';
174+
try {
175+
const release = await github.rest.repos.getReleaseByTag({
176+
owner: context.repo.owner,
177+
repo: context.repo.repo,
178+
tag: tag
179+
});
180+
core.setOutput('exists', 'true');
181+
core.setOutput('release_id', release.data.id);
182+
core.setOutput('is_prerelease', release.data.prerelease);
183+
console.log(`✅ Found release for tag ${tag}: ID ${release.data.id}`);
184+
} catch (error) {
185+
if (error.status === 404) {
186+
core.setOutput('exists', 'false');
187+
console.log(`ℹ️ No release found for tag ${tag}`);
188+
} else {
189+
throw error;
190+
}
191+
}
192+
193+
- name: Delete GitHub Release
194+
if: steps.check_release.outputs.exists == 'true'
195+
uses: actions/github-script@v7
196+
with:
197+
github-token: ${{ secrets.GITHUB_TOKEN }}
198+
script: |
199+
const releaseId = '${{ steps.check_release.outputs.release_id }}';
200+
const tag = '${{ env.TAG }}';
201+
202+
console.log(`🗑️ Deleting release ID ${releaseId} for tag ${tag}...`);
203+
204+
await github.rest.repos.deleteRelease({
205+
owner: context.repo.owner,
206+
repo: context.repo.repo,
207+
release_id: releaseId
208+
});
209+
210+
console.log(`✅ Release deleted successfully`);
211+
212+
// Also delete the tag if it exists
213+
try {
214+
await github.rest.git.deleteRef({
215+
owner: context.repo.owner,
216+
repo: context.repo.repo,
217+
ref: `tags/${tag}`
218+
});
219+
console.log(`✅ Tag ${tag} deleted successfully`);
220+
} catch (error) {
221+
if (error.status === 404) {
222+
console.log(`ℹ️ Tag ${tag} not found (may have been deleted already)`);
223+
} else {
224+
console.log(`⚠️ Could not delete tag ${tag}: ${error.message}`);
225+
}
226+
}
227+
228+
- name: Release not found
229+
if: steps.check_release.outputs.exists == 'false'
230+
run: |
231+
echo "ℹ️ No GitHub release found for tag ${{ env.TAG }}"
232+
echo "This is OK - the release may have already been deleted or never existed"
233+
234+
summary:
235+
name: "Summary"
236+
needs:
237+
- validate-version
238+
- revert-s3
239+
- reindex-linux-repos
240+
- unpublish-github-release
241+
if: always()
242+
runs-on: ubuntu-latest
243+
steps:
244+
- name: Print summary
245+
run: |
246+
echo "## Revert Summary" >> $GITHUB_STEP_SUMMARY
247+
echo "" >> $GITHUB_STEP_SUMMARY
248+
echo "**Version:** ${{ needs.validate-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
249+
echo "**Tag:** ${{ needs.validate-version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
250+
echo "**Dry Run:** ${{ github.event.inputs.dry_run }}" >> $GITHUB_STEP_SUMMARY
251+
echo "" >> $GITHUB_STEP_SUMMARY
252+
echo "### Completed Steps:" >> $GITHUB_STEP_SUMMARY
253+
echo "- ✅ Version validated" >> $GITHUB_STEP_SUMMARY
254+
echo "- ✅ Files removed from S3" >> $GITHUB_STEP_SUMMARY
255+
if [ "${{ github.event.inputs.dry_run }}" != "true" ]; then
256+
echo "- ✅ Linux repositories re-indexed" >> $GITHUB_STEP_SUMMARY
257+
echo "- ✅ GitHub release unpublished" >> $GITHUB_STEP_SUMMARY
258+
fi
259+
echo "" >> $GITHUB_STEP_SUMMARY
260+
echo "### Manual Steps Required:" >> $GITHUB_STEP_SUMMARY
261+
echo "- [ ] Revert PR in [keboola/homebrew-keboola-cli](https://github.com/keboola/homebrew-keboola-cli) that added version ${{ needs.validate-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
262+
echo "- [ ] Revert PR in [keboola/scoop-keboola-cli](https://github.com/keboola/scoop-keboola-cli) that added version ${{ needs.validate-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
263+
echo "- [ ] Check/close WinGet PR in [microsoft/winget-pkgs](https://github.com/microsoft/winget-pkgs)" >> $GITHUB_STEP_SUMMARY
264+
echo "- [ ] Unlist Chocolatey package (if possible) at [community.chocolatey.org](https://community.chocolatey.org/packages/keboola-cli)" >> $GITHUB_STEP_SUMMARY

build/ci/golangci.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
---
12
# Configuration Documentation
23
#
34
# This file configures golangci-lint, a Go linter aggregator that runs various linters
@@ -79,11 +80,11 @@ linters:
7980
- wastedassign
8081
- whitespace
8182
# DISABLED
82-
#- goimports # replaced with gci
83-
#- gofmt # replaced with gofumpt
84-
#- nolintlint # strange behavior
85-
#- gomoddirectives # allow replace directive in go.mod
86-
#- misspell - broken, rewrites code
83+
# - goimports # replaced with gci
84+
# - gofmt # replaced with gofumpt
85+
# - nolintlint # strange behavior
86+
# - gomoddirectives # allow replace directive in go.mod
87+
# - misspell - broken, rewrites code
8788
settings:
8889
depguard:
8990
rules:

0 commit comments

Comments
 (0)