Skip to content

feat: optional Bitcoin node + BTC wallet (bitcoind + BDK sidecar) #29

feat: optional Bitcoin node + BTC wallet (bitcoind + BDK sidecar)

feat: optional Bitcoin node + BTC wallet (bitcoind + BDK sidecar) #29

Workflow file for this run

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