Docker job builds multi-arch images (amd64/arm64) and pushes to DockerHub on each tagged release. VirusTotal job scans all release artifacts and appends results table to release notes.
162 lines
4.7 KiB
YAML
162 lines
4.7 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "v*"
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-go@v5
|
|
with:
|
|
go-version-file: go.mod
|
|
|
|
- uses: goreleaser/goreleaser-action@v6
|
|
with:
|
|
version: "~> v2"
|
|
args: release --clean
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
|
|
docker:
|
|
needs: release
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: torrentclaw/unarr
|
|
tags: |
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
type=raw,value=latest
|
|
|
|
- uses: docker/setup-qemu-action@v3
|
|
- uses: docker/setup-buildx-action@v3
|
|
|
|
- uses: docker/login-action@v3
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
push: true
|
|
platforms: linux/amd64,linux/arm64
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
VERSION=${{ github.ref_name }}
|
|
|
|
virustotal:
|
|
needs: release
|
|
runs-on: ubuntu-latest
|
|
if: ${{ secrets.VT_API_KEY != '' }}
|
|
steps:
|
|
- name: Get release tag
|
|
id: tag
|
|
run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Download release assets
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
mkdir -p assets
|
|
gh release download "${{ steps.tag.outputs.tag }}" \
|
|
--repo "${{ github.repository }}" \
|
|
--dir assets \
|
|
--pattern '*.tar.gz' \
|
|
--pattern '*.zip' \
|
|
--pattern 'checksums.txt'
|
|
|
|
- name: Scan assets with VirusTotal
|
|
env:
|
|
VT_API_KEY: ${{ secrets.VT_API_KEY }}
|
|
run: |
|
|
mkdir -p results
|
|
for file in assets/*; do
|
|
filename=$(basename "$file")
|
|
echo "Uploading $filename to VirusTotal..."
|
|
|
|
response=$(curl -s --request POST \
|
|
--url https://www.virustotal.com/api/v3/files \
|
|
--header "x-apikey: $VT_API_KEY" \
|
|
--form "file=@$file")
|
|
|
|
analysis_id=$(echo "$response" | jq -r '.data.id // empty')
|
|
if [ -z "$analysis_id" ]; then
|
|
echo "::warning::Failed to upload $filename: $response"
|
|
continue
|
|
fi
|
|
|
|
echo "$filename=$analysis_id" >> results/scans.txt
|
|
echo " Analysis ID: $analysis_id"
|
|
|
|
# Rate limit: VT free tier allows 4 req/min
|
|
sleep 16
|
|
done
|
|
|
|
- name: Wait for analysis completion
|
|
env:
|
|
VT_API_KEY: ${{ secrets.VT_API_KEY }}
|
|
run: |
|
|
echo "Waiting 60s for VirusTotal analysis to complete..."
|
|
sleep 60
|
|
|
|
vt_report="## 🛡️ VirusTotal Scan Results\n\n"
|
|
vt_report+="| File | Result | Link |\n"
|
|
vt_report+="|------|--------|------|\n"
|
|
|
|
while IFS='=' read -r filename analysis_id; do
|
|
result=$(curl -s --request GET \
|
|
--url "https://www.virustotal.com/api/v3/analyses/$analysis_id" \
|
|
--header "x-apikey: $VT_API_KEY")
|
|
|
|
malicious=$(echo "$result" | jq -r '.data.attributes.stats.malicious // 0')
|
|
undetected=$(echo "$result" | jq -r '.data.attributes.stats.undetected // 0')
|
|
sha256=$(echo "$result" | jq -r '.meta.file_info.sha256 // empty')
|
|
|
|
if [ "$malicious" = "0" ]; then
|
|
status="✅ Clean ($undetected engines)"
|
|
else
|
|
status="⚠️ $malicious detections"
|
|
fi
|
|
|
|
link="https://www.virustotal.com/gui/file/$sha256"
|
|
vt_report+="| \`$filename\` | $status | [View]($link) |\n"
|
|
|
|
sleep 16
|
|
done < results/scans.txt
|
|
|
|
echo -e "$vt_report" > results/report.md
|
|
cat results/report.md
|
|
|
|
- name: Append scan results to release notes
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
current_body=$(gh release view "${{ steps.tag.outputs.tag }}" \
|
|
--repo "${{ github.repository }}" \
|
|
--json body --jq '.body')
|
|
|
|
new_body="${current_body}
|
|
|
|
$(cat results/report.md)"
|
|
|
|
gh release edit "${{ steps.tag.outputs.tag }}" \
|
|
--repo "${{ github.repository }}" \
|
|
--notes "$new_body"
|