Skip to content

Commit ec3d439

Browse files
committed
automated release process
1 parent 2847b62 commit ec3d439

File tree

6 files changed

+350
-29
lines changed

6 files changed

+350
-29
lines changed

.github/workflows/cicd-to-dockerhub.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,29 @@ jobs:
3232

3333
- name: Image digest
3434
run: echo ${{ steps.docker_build.outputs.digest }}
35+
36+
- name: Verify pushed image
37+
run: |
38+
# Wait a moment for the image to be available
39+
sleep 5
40+
41+
# Pull the image we just pushed
42+
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/feroxbuster:latest
43+
44+
# Get the digest of the pulled image
45+
PULLED_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' ${{ secrets.DOCKER_HUB_USERNAME }}/feroxbuster:latest | cut -d'@' -f2)
46+
PUSHED_DIGEST="${{ steps.docker_build.outputs.digest }}"
47+
48+
echo "Pushed digest: $PUSHED_DIGEST"
49+
echo "Pulled digest: $PULLED_DIGEST"
50+
51+
# Verify they match
52+
if [ "$PULLED_DIGEST" = "$PUSHED_DIGEST" ]; then
53+
echo "✓ Verification successful: Pulled image matches pushed image"
54+
55+
# Test that the binary works
56+
docker run --rm ${{ secrets.DOCKER_HUB_USERNAME }}/feroxbuster:latest --version
57+
else
58+
echo "✗ Verification failed: Digests do not match"
59+
exit 1
60+
fi

.github/workflows/coverage.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@ name: Code Coverage Pipeline
44

55
jobs:
66
coverage:
7-
name: LLVM Coverage
7+
name: Tarpaulin Coverage
88
runs-on: ubuntu-latest
99
steps:
1010
- uses: actions/checkout@v4
1111
- uses: dtolnay/rust-toolchain@stable
12-
with:
13-
components: llvm-tools-preview
14-
- name: Install cargo-llvm-cov and cargo-nextest
12+
- name: Install cargo-tarpaulin
1513
uses: taiki-e/install-action@v2
1614
with:
17-
tool: cargo-nextest,cargo-llvm-cov
15+
tool: cargo-tarpaulin
1816
- name: Generate code coverage
19-
run: cargo llvm-cov nextest --all-features --no-fail-fast --lcov --retries 4 --output-path lcov.info
17+
run: cargo tarpaulin --all-features --workspace --timeout 300 --out lcov --output-dir .
2018
- name: Upload coverage to Codecov
2119
uses: codecov/codecov-action@v4
2220
with:

.github/workflows/release.yml

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
create-release:
13+
name: Create GitHub Release
14+
runs-on: ubuntu-latest
15+
outputs:
16+
upload_url: ${{ steps.create_release.outputs.upload_url }}
17+
version: ${{ steps.get_version.outputs.version }}
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0
22+
23+
- name: Get version from tag
24+
id: get_version
25+
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
26+
27+
- name: Generate changelog
28+
id: changelog
29+
run: |
30+
# Get previous tag
31+
PREV_TAG=$(git describe --abbrev=0 --tags HEAD^ 2>/dev/null || echo "")
32+
33+
if [ -z "$PREV_TAG" ]; then
34+
# First release, get all commits
35+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges)
36+
else
37+
# Get commits since previous tag
38+
CHANGELOG=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
39+
fi
40+
41+
# Create changelog file
42+
{
43+
echo "## What's Changed"
44+
echo ""
45+
echo "$CHANGELOG"
46+
echo ""
47+
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${GITHUB_REF_NAME}"
48+
} > CHANGELOG.md
49+
50+
cat CHANGELOG.md
51+
52+
- name: Create Release
53+
id: create_release
54+
uses: softprops/action-gh-release@v2
55+
with:
56+
body_path: CHANGELOG.md
57+
draft: false
58+
prerelease: false
59+
60+
download-and-upload-artifacts:
61+
name: Download & Upload Release Assets
62+
needs: create-release
63+
runs-on: ubuntu-latest
64+
steps:
65+
- uses: actions/checkout@v4
66+
67+
- name: Wait for CD Pipeline
68+
uses: lewagon/[email protected]
69+
with:
70+
ref: ${{ github.ref }}
71+
check-name: 'build-nix (ubuntu-x64)'
72+
repo-token: ${{ secrets.GITHUB_TOKEN }}
73+
wait-interval: 10
74+
75+
- name: Download all artifacts
76+
uses: actions/download-artifact@v4
77+
with:
78+
path: artifacts
79+
run-id: ${{ github.run_id }}
80+
github-token: ${{ secrets.GITHUB_TOKEN }}
81+
82+
- name: Display structure of downloaded files
83+
run: ls -R artifacts/
84+
85+
- name: Prepare release assets
86+
id: prepare
87+
run: |
88+
mkdir -p release-assets
89+
cd artifacts
90+
91+
# Process Linux x86_64 binary - create tar.gz
92+
if [ -d "x86_64-linux-feroxbuster" ]; then
93+
tar czf ../release-assets/x86_64-linux-feroxbuster.tar.gz -C x86_64-linux-feroxbuster feroxbuster
94+
fi
95+
96+
# Process Linux x86 binary - create tar.gz
97+
if [ -d "x86-linux-feroxbuster" ]; then
98+
tar czf ../release-assets/x86-linux-feroxbuster.tar.gz -C x86-linux-feroxbuster feroxbuster
99+
fi
100+
101+
# Process ARM binaries - create tar.gz
102+
if [ -d "armv7-linux-feroxbuster" ]; then
103+
tar czf ../release-assets/armv7-linux-feroxbuster.tar.gz -C armv7-linux-feroxbuster feroxbuster
104+
fi
105+
106+
if [ -d "aarch64-linux-feroxbuster" ]; then
107+
tar czf ../release-assets/aarch64-linux-feroxbuster.tar.gz -C aarch64-linux-feroxbuster feroxbuster
108+
fi
109+
110+
# Copy macOS tar.gz files (already compressed)
111+
if [ -f "x86_64-macos-feroxbuster.tar.gz/x86_64-macos-feroxbuster.tar.gz" ]; then
112+
cp x86_64-macos-feroxbuster.tar.gz/x86_64-macos-feroxbuster.tar.gz ../release-assets/
113+
fi
114+
115+
if [ -f "aarch64-macos-feroxbuster.tar.gz/aarch64-macos-feroxbuster.tar.gz" ]; then
116+
cp aarch64-macos-feroxbuster.tar.gz/aarch64-macos-feroxbuster.tar.gz ../release-assets/
117+
fi
118+
119+
# Copy Windows executables - create zip files
120+
if [ -d "x86_64-windows-feroxbuster.exe" ]; then
121+
cd x86_64-windows-feroxbuster.exe
122+
zip ../../release-assets/x86_64-windows-feroxbuster.zip feroxbuster.exe
123+
cd ..
124+
fi
125+
126+
if [ -d "x86-windows-feroxbuster.exe" ]; then
127+
cd x86-windows-feroxbuster.exe
128+
zip ../../release-assets/x86-windows-feroxbuster.zip feroxbuster.exe
129+
cd ..
130+
fi
131+
132+
# Copy .deb file
133+
if [ -d "feroxbuster_amd64.deb" ]; then
134+
cp feroxbuster_amd64.deb/*.deb ../release-assets/ || true
135+
fi
136+
137+
cd ..
138+
139+
# Generate SHA256 checksums
140+
cd release-assets
141+
sha256sum * > SHA256SUMS
142+
cat SHA256SUMS
143+
144+
# Extract specific hashes for homebrew
145+
LINUX_HASH=$(grep "x86_64-linux-feroxbuster.tar.gz" SHA256SUMS | awk '{print $1}')
146+
MACOS_X64_HASH=$(grep "x86_64-macos-feroxbuster.tar.gz" SHA256SUMS | awk '{print $1}')
147+
MACOS_ARM_HASH=$(grep "aarch64-macos-feroxbuster.tar.gz" SHA256SUMS | awk '{print $1}')
148+
149+
echo "linux_hash=$LINUX_HASH" >> $GITHUB_OUTPUT
150+
echo "macos_x64_hash=$MACOS_X64_HASH" >> $GITHUB_OUTPUT
151+
echo "macos_arm_hash=$MACOS_ARM_HASH" >> $GITHUB_OUTPUT
152+
153+
- name: Upload Release Assets
154+
uses: softprops/action-gh-release@v2
155+
with:
156+
files: release-assets/*
157+
158+
publish-crates-io:
159+
name: Publish to crates.io
160+
needs: create-release
161+
runs-on: ubuntu-latest
162+
steps:
163+
- uses: actions/checkout@v4
164+
165+
- name: Install Rust toolchain
166+
uses: dtolnay/rust-toolchain@stable
167+
168+
- name: Publish to crates.io
169+
env:
170+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
171+
run: cargo publish
172+
173+
update-homebrew:
174+
name: Update Homebrew Taps
175+
needs: [create-release, download-and-upload-artifacts]
176+
runs-on: ubuntu-latest
177+
steps:
178+
- name: Checkout TGotwig's homebrew-linux-feroxbuster
179+
uses: actions/checkout@v4
180+
with:
181+
repository: TGotwig/homebrew-linux-feroxbuster
182+
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
183+
path: homebrew-linux
184+
185+
- name: Update Linux formula
186+
run: |
187+
cd homebrew-linux
188+
VERSION="${{ needs.create-release.outputs.version }}"
189+
HASH="${{ needs.download-and-upload-artifacts.outputs.linux_hash }}"
190+
191+
# Update version and hash in formula
192+
sed -i "s|url \"https://github.com/epi052/feroxbuster/releases/download/v[^/]*/x86_64-linux-feroxbuster.tar.gz\"|url \"https://github.com/epi052/feroxbuster/releases/download/v${VERSION}/x86_64-linux-feroxbuster.tar.gz\"|g" feroxbuster.rb
193+
sed -i "s/sha256 \"[^\"]*\"/sha256 \"${HASH}\"/g" feroxbuster.rb
194+
195+
git config user.name "github-actions[bot]"
196+
git config user.email "github-actions[bot]@users.noreply.github.com"
197+
git add feroxbuster.rb
198+
git commit -m "Update feroxbuster to v${VERSION}" || echo "No changes to commit"
199+
git push
200+
201+
- name: Checkout feroxbuster main repo to get config
202+
uses: actions/checkout@v4
203+
with:
204+
path: feroxbuster-src
205+
206+
- name: Check if config changed
207+
id: config_check
208+
run: |
209+
cd feroxbuster-src
210+
CONFIG_HASH=$(sha256sum ferox-config.toml.example | awk '{print $1}')
211+
echo "config_hash=$CONFIG_HASH" >> $GITHUB_OUTPUT
212+
213+
# Check if config changed since last tag
214+
PREV_TAG=$(git describe --abbrev=0 --tags HEAD^ 2>/dev/null || echo "")
215+
if [ -n "$PREV_TAG" ]; then
216+
if git diff ${PREV_TAG}..HEAD --quiet -- ferox-config.toml.example; then
217+
echo "config_changed=false" >> $GITHUB_OUTPUT
218+
else
219+
echo "config_changed=true" >> $GITHUB_OUTPUT
220+
fi
221+
else
222+
echo "config_changed=true" >> $GITHUB_OUTPUT
223+
fi
224+
225+
- name: Update config hash in homebrew if changed
226+
if: steps.config_check.outputs.config_changed == 'true'
227+
run: |
228+
cd homebrew-linux
229+
CONFIG_HASH="${{ steps.config_check.outputs.config_hash }}"
230+
231+
# Update config hash if it exists in formula
232+
if grep -q "ferox-config.toml.example" feroxbuster.rb; then
233+
sed -i "s/sha256 \"[^\"]*\" # ferox-config.toml.example/sha256 \"${CONFIG_HASH}\" # ferox-config.toml.example/g" feroxbuster.rb
234+
235+
git add feroxbuster.rb
236+
git commit -m "Update ferox-config.toml.example hash" || echo "No changes to commit"
237+
git push
238+
fi
239+
240+
publish-winget:
241+
name: Publish to Winget
242+
needs: [create-release, download-and-upload-artifacts]
243+
runs-on: ubuntu-latest
244+
steps:
245+
- uses: vedantmgoyal2009/winget-releaser@main
246+
with:
247+
identifier: epi052.feroxbuster
248+
installers-regex: '-windows-feroxbuster\.exe\.zip$'
249+
token: ${{ secrets.WINGET_TOKEN }}
250+
release-tag: v${{ needs.create-release.outputs.version }}
251+
252+
publish-snapcraft:
253+
name: Publish to Snapcraft
254+
needs: [create-release, download-and-upload-artifacts]
255+
runs-on: ubuntu-latest
256+
steps:
257+
- uses: actions/checkout@v4
258+
259+
- name: Publish to Snapcraft
260+
uses: snapcore/action-publish@v1
261+
env:
262+
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
263+
with:
264+
snap: feroxbuster
265+
release: stable
266+
267+
manual-steps-reminder:
268+
name: Manual Steps Reminder
269+
needs: [create-release, download-and-upload-artifacts]
270+
runs-on: ubuntu-latest
271+
steps:
272+
- name: Create comment with manual steps
273+
uses: actions/github-script@v7
274+
with:
275+
script: |
276+
const version = '${{ needs.create-release.outputs.version }}';
277+
const linuxHash = '${{ needs.download-and-upload-artifacts.outputs.linux_hash }}';
278+
279+
const body = `## 🚀 Release v${version} Published!
280+
281+
### ✅ Automated Steps Completed
282+
- [x] GitHub Release created with changelog
283+
- [x] All artifacts uploaded with SHA256 checksums
284+
- [x] Published to crates.io
285+
- [x] Homebrew tap updated
286+
- [x] Winget package published
287+
- [x] Snapcraft published to stable
288+
289+
### 📋 Manual Steps Required
290+
291+
1. **Kali Linux**
292+
- Go to https://bugs.kali.org/login_page.php?return=%2Fmy_view_page.php
293+
- Request a tool update
294+
295+
3. **Announcement** (optional)
296+
- Tweet about the release if it's significant!
297+
298+
2. **Announcement** (optional)
299+
- Linux x86_64: \`${linuxHash}\`
300+
301+
See full checksums in release assets: SHA256SUMS
302+
`;
303+
304+
github.rest.issues.createComment({
305+
owner: context.repo.owner,
306+
repo: context.repo.repo,
307+
issue_number: context.issue.number,
308+
body: body
309+
});

.github/workflows/winget.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

Makefile.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,12 @@ condition = { env_not_set = ["CI"] }
5050
clear = true
5151
script = """
5252
cargo nextest run --all-features --all-targets --no-fail-fast --run-ignored all --retries 4
53+
"""
54+
55+
# coverage
56+
[tasks.coverage]
57+
clear = true
58+
script = """
59+
cargo tarpaulin --all-features --workspace --timeout 300 --out html --output-dir target/coverage
60+
echo "Coverage report generated at target/coverage/index.html"
5361
"""

0 commit comments

Comments
 (0)