diff --git a/.github/workflows/check-docker-config.yaml b/.github/workflows/check-docker-config.yaml new file mode 100644 index 000000000..bc66d4cf6 --- /dev/null +++ b/.github/workflows/check-docker-config.yaml @@ -0,0 +1,19 @@ +name: Validate Docker Config Drift + +on: + pull_request: + branches: + - main + +jobs: + validate-config: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Validate config vs Docker templates + run: | + bash scripts/validate-docker-config.sh + diff --git a/.github/workflows/docker-release.yaml b/.github/workflows/docker-release.yaml index be6d47537..2aa2fea9e 100644 --- a/.github/workflows/docker-release.yaml +++ b/.github/workflows/docker-release.yaml @@ -1,6 +1,10 @@ -name: Build and Push Docker Images on Release +name: Build and Push Docker Images on: + push: + branches: + - main + release: types: [published] workflow_dispatch: @@ -43,7 +47,5 @@ jobs: linux/arm64 tags: | - stratumv2/${{ matrix.app }}:latest stratumv2/${{ matrix.app }}:${{ github.ref_name }} - diff --git a/docker/README.md b/docker/README.md index a9447fbe4..47489acb9 100644 --- a/docker/README.md +++ b/docker/README.md @@ -166,14 +166,14 @@ Tags start at **`v0.1.0`** and will continue incrementing with future releases. You can choose: * A **specific version tag** (e.g. `v0.1.0`) for predictable, repeatable deployments. -* The **`latest`** tag if you simply want the most recent released image. +* The **`main`** tag if you want the most recent updates of the main branch of the repository. Example: ```yaml image: pool_sv2:v0.1.0 # pinned version # or -image: pool_sv2:latest # latest release +image: pool_sv2:main #latest changes in the main branch ``` This applies to all images: `pool_sv2`, `jd_server`, `jd_client_sv2`, and `translator_sv2`. diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index be24e393d..d8484e1e1 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,6 +1,6 @@ services: pool_sv2: - image: stratumv2/pool_sv2:v0.1.0 + image: stratumv2/pool_sv2:main container_name: pool_sv2 env_file: - docker_env @@ -25,7 +25,7 @@ services: jd_server_sv2: - image: stratumv2/jd_server:v0.1.0 + image: stratumv2/jd_server:main container_name: jd_server_sv2 env_file: - docker_env @@ -49,7 +49,7 @@ services: - pool_and_miner_apps jd_client_sv2: - image: stratumv2/jd_client_sv2:v0.1.0 + image: stratumv2/jd_client_sv2:main container_name: jd_client_sv2 env_file: - docker_env @@ -72,7 +72,7 @@ services: - pool_and_miner_apps tproxy_sv2: - image: stratumv2/translator_sv2:v0.1.0 + image: stratumv2/translator_sv2:main container_name: tproxy_sv2 env_file: - docker_env diff --git a/scripts/validate-docker-config.sh b/scripts/validate-docker-config.sh new file mode 100755 index 000000000..a9ff96834 --- /dev/null +++ b/scripts/validate-docker-config.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +set -euo pipefail + + +CONFIG_FILES=( + "pool-apps/pool/config-examples/mainnet/pool-config-bitcoin-core-ipc-example.toml" + "pool-apps/jd-server/config-examples/mainnet/jds-config-local-example.toml" + "miner-apps/jd-client/config-examples/mainnet/jdc-config-bitcoin-core-ipc-hosted-infra-example.toml" + "miner-apps/translator/config-examples/mainnet/tproxy-config-local-jdc-example.toml" +) + +get_template_for_config() { + case "$1" in + pool-apps/pool/config-examples/mainnet/pool-config-bitcoin-core-ipc-example.toml) + echo "docker/config/pool-config.toml.template" + ;; + pool-apps/jd-server/config-examples/mainnet/jds-config-local-example.toml) + echo "docker/config/jds-config.toml.template" + ;; + miner-apps/jd-client/config-examples/mainnet/jdc-config-bitcoin-core-ipc-hosted-infra-example.toml) + echo "docker/config/jdc-config.toml.template" + ;; + miner-apps/translator/config-examples/mainnet/tproxy-config-local-jdc-example.toml) + echo "docker/config/translator-proxy-config.toml.template" + ;; + *) + echo "" + ;; + esac +} + +# WARNING: Implemented with GPT-5 +# +# Extracts key names from a TOML-like file. +# +# Behavior: +# - Ignores comments and blank lines +# - Tracks the current [section] +# - For lines containing '=', treats the left-hand side as a key +# - Outputs keys as "section.key" or "key" if no section is active +# - Sorts and removes duplicates +# +# Limitations: +# - Not a full TOML parser +# - Does not handle quoted keys, inline tables, arrays, multiline strings, +# escapes, or nested sections +extract_keys() { + local file="$1" + + awk ' + /^[[:space:]]*#/ { next } + /^[[:space:]]*$/ { next } + + /^\[.*\]$/ { + section=$0 + gsub(/[\[\]]/, "", section) + next + } + + /=/ { + split($0, a, "=") + key=a[1] + gsub(/[[:space:]]+$/, "", key) + + if (section != "") + print section "." key + else + print key + } +' "$file" | sort -u +} + +echo "Validating TOML structure against Docker templates" +echo + +FAILED=0 + +for CONFIG_FILE in "${CONFIG_FILES[@]}"; do + TEMPLATE_FILE="$(get_template_for_config "$CONFIG_FILE")" + + if [[ -z "$TEMPLATE_FILE" ]]; then + echo "❌ No Docker template mapped for $CONFIG_FILE" + FAILED=1 + continue + fi + + if [[ ! -f "$CONFIG_FILE" ]]; then + echo "⚠️ Missing config file: $CONFIG_FILE" + FAILED=1 + continue + fi + + if [[ ! -f "$TEMPLATE_FILE" ]]; then + echo "❌ Missing Docker template: $TEMPLATE_FILE" + FAILED=1 + continue + fi + + echo "▶ Comparing" + echo " Config: $CONFIG_FILE" + echo " Template: $TEMPLATE_FILE" + + CONFIG_KEYS=$(extract_keys "$CONFIG_FILE") + TEMPLATE_KEYS=$(extract_keys "$TEMPLATE_FILE") + +DIFF=$(diff -u -U0 <(echo "$TEMPLATE_KEYS") <(echo "$CONFIG_KEYS") \ + | grep -E '^[+-]' || true) + + if [[ -n "$DIFF" ]]; then + echo + echo "❌ Config / Docker drift detected" + echo + echo "$DIFF" + echo + FAILED=1 + else + echo "✅ In sync" + echo + fi +done + +if [[ "$FAILED" -ne 0 ]]; then + echo "🚨 Docker templates are out of sync with config examples." + echo "👉 Update the Docker templates to reflect all config keys." + exit 1 +fi + +echo "All Docker templates match their configs." +