fix(init): pre-create uploads/ so the bind mount is not root-owned #30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docker Images | |
| # Builds the deployable images (web-gui, bdk-wallet, btc-explorer) for | |
| # amd64 + arm64 so a VPS / Raspberry Pi can `docker compose pull` without | |
| # building anything locally. | |
| # | |
| # Native builds on GitHub's free amd64 + arm64 runners (public repos); | |
| # per-arch images pushed as <ref>-amd64 / -arm64, then merged into | |
| # multi-arch manifests. This mirrors mintlayer-daemons.yml: buildx | |
| # multi-platform pushes with provenance attestations produced indexes | |
| # GHCR would not serve (manifest unknown on pull, even by digest). | |
| # | |
| # - push to main -> ghcr.io/mintlayer/web-gui/<image>:latest (+ :sha) | |
| # - push to other branches-> ghcr.io/mintlayer/web-gui/<image>:br-<branch> | |
| # - tag v* -> ghcr.io/mintlayer/web-gui/<image>:v<tag> | |
| # - pull_request -> build only (no push), catches Dockerfile breakage | |
| on: | |
| push: | |
| branches: ["**"] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| REGISTRY: ghcr.io | |
| OWNER: mintlayer | |
| IMAGE_NS: ghcr.io/mintlayer/web-gui | |
| IMAGES: "web-gui bdk-wallet btc-explorer" | |
| permissions: | |
| contents: read | |
| packages: write | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: amd64 | |
| runs-on: ubuntu-latest | |
| - arch: arm64 | |
| runs-on: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runs-on }} | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| # The bdk-wallet release build needs serious disk; prune the runner's | |
| # big preinstalls. | |
| - name: Free disk space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \ | |
| /opt/hostedtoolcache/CodeQL /usr/local/share/boost || true | |
| sudo docker image prune -af || true | |
| df -h / | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| if: github.event_name != 'pull_request' | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compute tag base | |
| id: tagbase | |
| if: github.event_name != 'pull_request' | |
| env: | |
| GITHUB_DEFAULT_BRANCH: main | |
| run: | | |
| if [[ "$GITHUB_REF" == "refs/tags/v"* ]]; then | |
| echo "base=v${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" | |
| elif [[ "$GITHUB_REF_NAME" == "$GITHUB_DEFAULT_BRANCH" ]]; then | |
| echo "base=latest" >> "$GITHUB_OUTPUT" | |
| else | |
| base="br-${GITHUB_REF_NAME//\//-}" | |
| echo "base=$base" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "sha=sha-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" | |
| - name: Build and push per-arch images | |
| if: github.event_name != 'pull_request' | |
| env: | |
| BASE: ${{ steps.tagbase.outputs.base }} | |
| SHA_TAG: ${{ steps.tagbase.outputs.sha }} | |
| ARCH: ${{ matrix.arch }} | |
| run: | | |
| set -eu | |
| declare -A CONTEXTS=( [web-gui]=./app [bdk-wallet]=./bdk-wallet [btc-explorer]=./btc-explorer ) | |
| for image in $IMAGES; do | |
| for variant in "$BASE" "$SHA_TAG"; do | |
| docker buildx build \ | |
| --platform "linux/$ARCH" \ | |
| --provenance=false \ | |
| --push \ | |
| -t "$IMAGE_NS/$image:$variant-$ARCH" \ | |
| "${CONTEXTS[$image]}" | |
| done | |
| done | |
| - name: Build only (pull_request) | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| set -eu | |
| declare -A CONTEXTS=( [web-gui]=./app [bdk-wallet]=./bdk-wallet [btc-explorer]=./btc-explorer ) | |
| for image in $IMAGES; do | |
| docker buildx build \ | |
| --platform "linux/${{ matrix.arch }}" \ | |
| --provenance=false \ | |
| --load \ | |
| "${CONTEXTS[$image]}" | |
| done | |
| manifest: | |
| needs: build | |
| if: github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| env: | |
| DOCKER_CLI_EXPERIMENTAL: enabled | |
| steps: | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compute tag base | |
| id: tagbase | |
| env: | |
| GITHUB_DEFAULT_BRANCH: main | |
| run: | | |
| if [[ "$GITHUB_REF" == "refs/tags/v"* ]]; then | |
| echo "base=v${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" | |
| elif [[ "$GITHUB_REF_NAME" == "main" ]]; then | |
| echo "base=latest" >> "$GITHUB_OUTPUT" | |
| else | |
| base="br-${GITHUB_REF_NAME//\//-}" | |
| echo "base=$base" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "sha=sha-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" | |
| - name: Create and push multi-arch manifests | |
| env: | |
| BASE: ${{ steps.tagbase.outputs.base }} | |
| SHA_TAG: ${{ steps.tagbase.outputs.sha }} | |
| ARCHES: "amd64 arm64" | |
| IMAGE_NS: ${{ env.IMAGE_NS }} | |
| run: | | |
| set -eu | |
| # GHCR is eventually consistent right after a push: manifest | |
| # creates can hit "manifest unknown" for a minute or two. Retry. | |
| sleep 30 | |
| for image in $IMAGES; do | |
| for variant in "$BASE" "$SHA_TAG"; do | |
| args=() | |
| for arch in $ARCHES; do | |
| args+=("--amend" "$IMAGE_NS/$image:$variant-$arch") | |
| done | |
| attempt=1 | |
| until docker manifest create "$IMAGE_NS/$image:$variant" "${args[@]}" >/dev/null; do | |
| if [ "$attempt" -ge 6 ]; then | |
| echo "::error::manifest create failed for $IMAGE_NS/$image:$variant after $attempt attempts" | |
| exit 1 | |
| fi | |
| echo "attempt $attempt failed - retrying in 30s" | |
| sleep 30 | |
| attempt=$((attempt + 1)) | |
| done | |
| docker manifest push "$IMAGE_NS/$image:$variant" | |
| done | |
| done |