Files
2026-07-08 13:07:57 +02:00

247 lines
9.1 KiB
YAML

name: Docker Build and Push
permissions:
contents: write
packages: write
on:
workflow_dispatch:
inputs:
branch:
type: choice
description: Target branch
options: [develop, master]
default: develop
choice:
type: choice
description: Version bump
options: [none, major, minor, patch]
default: none
push:
branches: [develop, master]
# Avoid multiple parallel builds for the same branch to prevent race conditions
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false # Set to true if you want to abort old builds immediately
jobs:
docker-build:
runs-on: ubuntu-latest
if: >-
(github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') &&
(github.event_name != 'push' || github.actor != 'github-actions[bot]')
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0
# Ensure we always have the right branch context
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.branch || github.ref }}
- name: Install Rust Tools (Binaries)
uses: taiki-e/install-action@v2
with:
tool: cross,trunk,wasm-bindgen-cli,cargo-edit,mdbook
- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-musl,aarch64-unknown-linux-musl,wasm32-unknown-unknown
- name: Install wasm tools 128
run: |
chmod +x ./bin/install_wasm_tools.sh
WASM_TOOLS_BIN="$(./bin/install_wasm_tools.sh 128)"
echo "${WASM_TOOLS_BIN}" >> "$GITHUB_PATH"
- name: Rust Cache
uses: Swatinem/rust-cache@v2
with:
cache-targets: "true"
- name: Handle Version Bump
run: |
chmod +x ./bin/inc_version.sh
if [[ "${{ github.event_name }}" == "push" ]]; then
case "${{ github.ref_name }}" in
develop) ./bin/inc_version.sh ;;
master) echo "Master builds use the version already committed in the merged PR; skipping version bump." ;;
*) echo "Unsupported push branch: ${{ github.ref_name }}" >&2; exit 1 ;;
esac
else
if [[ "${{ github.event.inputs.branch }}" == "master" ]]; then
echo "Manual master builds use the version already committed on master; skipping version bump."
else
case "${{ github.event.inputs.choice }}" in
major) ./bin/inc_version.sh m ;;
minor) ./bin/inc_version.sh p ;;
patch) ./bin/inc_version.sh ;;
esac
fi
fi
- name: Read project version
id: version
run: |
VERSION=$(grep -Po '^version\s*=\s*"\K[0-9\.]+' ./Cargo.toml)
echo "value=${VERSION}" >> "$GITHUB_OUTPUT"
- name: Enforce zero patch for master releases
if: >-
(github.event_name == 'workflow_dispatch' && github.event.inputs.branch == 'master') ||
(github.event_name == 'push' && github.ref == 'refs/heads/master')
run: |
VERSION="${{ steps.version.outputs.value }}"
IFS='.' read -r major minor patch <<< "${VERSION}"
if [[ -z "${major}" || -z "${minor}" || -z "${patch}" ]]; then
echo "🧨 Invalid semantic version: ${VERSION}" >&2
exit 1
fi
if [[ "${patch}" != "0" ]]; then
echo "🧨 Refusing master release for non-release version ${VERSION}. Patch component must be 0." >&2
exit 1
fi
- name: Set up QEMU
uses: docker/setup-qemu-action@v4.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4.2.0
- name: Cache built resources
id: cache-resources
uses: actions/cache@v5
with:
path: resources/*.ts
key: ${{ runner.os }}-resources-${{ hashFiles('resources/*.jpg') }}
- name: Install ffmpeg
if: steps.cache-resources.outputs.cache-hit != 'true'
run: |
sudo apt-get update
sudo apt-get install -y ffmpeg
- name: Build TS resources
if: steps.cache-resources.outputs.cache-hit != 'true'
run: |
chmod +x ./bin/build_resources.sh
./bin/build_resources.sh
- name: Verify TS resources
run: |
required_resources=(
"channel_unavailable"
"user_connections_exhausted"
"provider_connections_exhausted"
"user_account_expired"
"panel_api_provisioning"
)
for resource in "${required_resources[@]}"; do
if [[ ! -f "resources/${resource}.ts" ]]; then
echo "🧨 Missing resource: resources/${resource}.ts"
exit 1
fi
done
- name: Commit version bump
if: >-
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.branch != 'master')
id: version_commit
run: |
git config user.name "euzu"
git config user.email "euzu@proton.me"
git add .
if git diff --cached --quiet; then
echo "did_commit=false" >> "$GITHUB_OUTPUT"
else
VERSION=$(grep -Po '^version\s*=\s*"\K[0-9\.]+' ./Cargo.toml | head -n1)
git commit -m "ci: bump version v$VERSION"
# Delete local tag if it exists (from a previous failed run)
git tag -d "v$VERSION" 2>/dev/null || true
git tag -a "v$VERSION" -m "v$VERSION"
echo "did_commit=true" >> "$GITHUB_OUTPUT"
fi
- name: Build and push Docker images
env:
GITHUB_IO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO_OWNER: ${{ github.repository_owner }}
run: |
chmod +x ./bin/build_docker.sh
./bin/build_docker.sh ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.branch || github.ref_name }}
- name: Verify release bundle artifacts
run: |
ls -la artifacts
for arch in x86_64-unknown-linux-musl aarch64-unknown-linux-musl; do
artifact="artifacts/tuliprox-v${{ steps.version.outputs.value }}-${arch}.tar.gz"
test -f "${artifact}"
test -f "${artifact}.sha256"
for required_path in tuliprox/tuliprox tuliprox/web/ tuliprox/resources/; do
tar -tzf "${artifact}" | grep -qx "${required_path}"
done
done
for sum_file in artifacts/*.sha256; do
(cd artifacts && sha256sum -c "$(basename "$sum_file")")
done
- name: Build release checksum notes
run: |
{
echo "## Release Bundle Checksums"
echo
echo "The checksums below were validated in CI via \`sha256sum -c\` before upload."
echo
echo "| File | SHA256 |"
echo "| --- | --- |"
for sum_file in artifacts/*.sha256; do
checksum=$(awk '{print $1}' "$sum_file")
filename=$(awk '{print $2}' "$sum_file")
echo "| \`$filename\` | \`$checksum\` |"
done
echo
echo "Verification command after download:"
echo "\`\`\`bash"
echo "sha256sum -c *.sha256"
echo "\`\`\`"
} > artifacts/RELEASE_NOTES_SHA256.md
- name: Upload release bundle artifacts
uses: actions/upload-artifact@v4
with:
name: tuliprox-release-v${{ steps.version.outputs.value }}
path: artifacts/*
if-no-files-found: error
- name: Push version bump
if: >-
success() &&
(
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.branch != 'master')
) &&
steps.version_commit.outputs.did_commit == 'true'
run: |
# Use origin HEAD to push to the correct remote branch, and push tags
git push origin HEAD --tags
- name: Publish release bundles to GitHub Release
if: >-
success() && (
(github.event_name == 'workflow_dispatch' && github.event.inputs.branch == 'master') ||
(github.event_name == 'push' && github.ref == 'refs/heads/master')
)
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version.outputs.value }}
name: v${{ steps.version.outputs.value }}
files: |
artifacts/tuliprox-v${{ steps.version.outputs.value }}-x86_64-unknown-linux-musl.tar.gz
artifacts/tuliprox-v${{ steps.version.outputs.value }}-x86_64-unknown-linux-musl.tar.gz.sha256
artifacts/tuliprox-v${{ steps.version.outputs.value }}-aarch64-unknown-linux-musl.tar.gz
artifacts/tuliprox-v${{ steps.version.outputs.value }}-aarch64-unknown-linux-musl.tar.gz.sha256
body_path: artifacts/RELEASE_NOTES_SHA256.md
generate_release_notes: true