mirror of
https://github.com/euzu/tuliprox.git
synced 2026-09-16 22:22:19 +02:00
247 lines
9.1 KiB
YAML
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
|