fix(bootstrap): PROXBOX_SKIP_NETBOX_BOOTSTRAP for Docker CI #6
Workflow file for this run
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
| # Runtime + mkcert images (nginx → uvicorn). Triggers: | |
| # - workflow_call: CI (main/testing) and release → always build, test, push (parallel jobs). | |
| # - workflow_dispatch: manual — test-only (no Hub) or full publish (parallel jobs, same as call). | |
| name: Docker images | |
| on: | |
| workflow_call: | |
| inputs: | |
| checkout_ref: | |
| description: Git ref to build (release tag); empty uses github.sha | |
| type: string | |
| required: false | |
| default: "" | |
| pull_request: | |
| branches: [main, testing] | |
| workflow_dispatch: | |
| inputs: | |
| git_ref: | |
| description: Branch, tag, or SHA to build | |
| type: string | |
| required: true | |
| default: main | |
| mode: | |
| description: >- | |
| build-and-test-only — amd64 build + in-container tests, no Docker Hub. | |
| publish — same as CI/release (push runtime + mkcert, multi-arch). | |
| type: choice | |
| required: true | |
| options: | |
| - build-and-test-only | |
| - publish | |
| default: build-and-test-only | |
| permissions: | |
| contents: read | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| # Sequential local test (manual); no registry login or push. | |
| docker-manual: | |
| if: github.event_name == 'workflow_dispatch' && inputs.mode == 'build-and-test-only' | |
| name: Docker — build and test only (manual) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ inputs.git_ref }} | |
| - name: Validate pyproject version vs tag ref | |
| id: version | |
| env: | |
| GIT_REF: ${{ inputs.git_ref }} | |
| run: | | |
| python3 <<'PY' | |
| import os | |
| import pathlib | |
| import tomllib | |
| git_ref = os.environ["GIT_REF"].strip() | |
| version = tomllib.loads( | |
| pathlib.Path("pyproject.toml").read_text(encoding="utf-8") | |
| )["project"]["version"] | |
| expected_tag = f"v{version}" | |
| if git_ref.startswith("v") and git_ref != expected_tag: | |
| raise SystemExit( | |
| f"git_ref/version mismatch: ref={git_ref!r}, expected {expected_tag!r}" | |
| ) | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh: | |
| fh.write(f"tag={version}\n") | |
| PY | |
| - name: Keep image tag in env | |
| run: echo "IMAGE_TAG=${{ steps.version.outputs.tag }}" >> $GITHUB_ENV | |
| - name: Create Docker test script | |
| run: | | |
| cat <<'EOF' > /tmp/docker-tests.sh | |
| #!/bin/sh | |
| set -eux | |
| # tests/ is bind-mounted read-only; keep bytecode out of the tree | |
| export PYTHONPYCACHEPREFIX=/tmp/pycache | |
| mkdir -p "$PYTHONPYCACHEPREFIX" | |
| export PROXBOX_SKIP_NETBOX_BOOTSTRAP=1 | |
| uv sync --frozen --extra test --group dev | |
| uv run ruff check . | |
| uv run ruff format --check . | |
| uv run python -m compileall proxbox_api scripts tests | |
| uv run python -c "import proxbox_api.main" | |
| uv run python -c "from proxbox_api.proxmox_to_netbox.proxmox_schema import load_proxmox_generated_openapi; assert load_proxmox_generated_openapi().get('paths')" | |
| uv run pytest --cov=proxbox_api --cov-report=term-missing --cov-report=xml tests --ignore=tests/e2e | |
| EOF | |
| chmod +x /tmp/docker-tests.sh | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| driver: docker-container | |
| - name: Build amd64 image for in-container tests | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: runtime | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-pre | |
| cache-from: type=gha,scope=runtime | |
| cache-to: type=gha,mode=max,scope=runtime | |
| - name: Run tests in local image | |
| run: | | |
| docker run --rm \ | |
| -v /tmp/docker-tests.sh:/tmp/docker-tests.sh \ | |
| -v "${{ github.workspace }}/tests:/app/tests:ro" \ | |
| emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-pre \ | |
| /tmp/docker-tests.sh | |
| - name: Build amd64 mkcert image for in-container tests | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: mkcert | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-mkcert-pre | |
| cache-from: type=gha,scope=mkcert | |
| cache-to: type=gha,mode=max,scope=mkcert | |
| - name: Run tests in mkcert local image | |
| run: | | |
| docker run --rm \ | |
| -v /tmp/docker-tests.sh:/tmp/docker-tests.sh \ | |
| -v "${{ github.workspace }}/tests:/app/tests:ro" \ | |
| emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-mkcert-pre \ | |
| /tmp/docker-tests.sh | |
| docker-runtime: | |
| if: github.event_name == 'workflow_call' || github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && inputs.mode == 'publish') | |
| name: Docker Hub — runtime (nginx + uvicorn) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.git_ref || github.event_name == 'workflow_call' && (inputs.checkout_ref != '' && inputs.checkout_ref || github.sha) || github.sha }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| # Required for cache-to: gha together with load: true (docker driver cannot export cache). | |
| driver: docker-container | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Resolve image version from pyproject | |
| id: version | |
| env: | |
| GIT_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.git_ref || github.event_name == 'workflow_call' && (inputs.checkout_ref != '' && inputs.checkout_ref || github.ref_name) || github.ref_name }} | |
| run: | | |
| python3 <<'PY' | |
| import os | |
| import pathlib | |
| import tomllib | |
| data = tomllib.loads(pathlib.Path("pyproject.toml").read_text(encoding="utf-8")) | |
| version = data["project"]["version"] | |
| expected_tag = f"v{version}" | |
| git_ref = os.environ["GIT_REF"].strip() | |
| if git_ref.startswith("v") and git_ref != expected_tag: | |
| raise SystemExit( | |
| f"git ref / pyproject mismatch: ref={git_ref!r}, expected {expected_tag!r}" | |
| ) | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh: | |
| fh.write(f"tag={version}\n") | |
| PY | |
| - name: Keep image tag in env | |
| run: echo "IMAGE_TAG=${{ steps.version.outputs.tag }}" >> $GITHUB_ENV | |
| - name: Create Docker test script | |
| run: | | |
| cat <<'EOF' > /tmp/docker-tests.sh | |
| #!/bin/sh | |
| set -eux | |
| # tests/ is bind-mounted read-only; keep bytecode out of the tree | |
| export PYTHONPYCACHEPREFIX=/tmp/pycache | |
| mkdir -p "$PYTHONPYCACHEPREFIX" | |
| export PROXBOX_SKIP_NETBOX_BOOTSTRAP=1 | |
| uv sync --frozen --extra test --group dev | |
| uv run ruff check . | |
| uv run ruff format --check . | |
| uv run python -m compileall proxbox_api scripts tests | |
| uv run python -c "import proxbox_api.main" | |
| uv run python -c "from proxbox_api.proxmox_to_netbox.proxmox_schema import load_proxmox_generated_openapi; assert load_proxmox_generated_openapi().get('paths')" | |
| uv run pytest --cov=proxbox_api --cov-report=term-missing --cov-report=xml tests --ignore=tests/e2e | |
| EOF | |
| chmod +x /tmp/docker-tests.sh | |
| - name: Build amd64 image for pre-release tests | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: runtime | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-pre | |
| cache-from: type=gha,scope=runtime | |
| cache-to: type=gha,mode=max,scope=runtime | |
| - name: Run pre-release tests in Docker image (runtime / nginx→uvicorn) | |
| run: | | |
| docker run --rm \ | |
| -v /tmp/docker-tests.sh:/tmp/docker-tests.sh \ | |
| -v "${{ github.workspace }}/tests:/app/tests:ro" \ | |
| emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-pre \ | |
| /tmp/docker-tests.sh | |
| - name: Extract metadata (labels, etc.) | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: emersonfelipesp/proxbox-api | |
| tags: | | |
| type=raw,value=${{ steps.version.outputs.tag }} | |
| type=raw,value=latest | |
| type=ref,event=pr | |
| type=sha | |
| - name: Build and push Docker image (runtime) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: runtime | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=runtime | |
| cache-to: type=gha,mode=max,scope=runtime | |
| - name: Pull and verify pushed runtime images | |
| run: | | |
| docker pull emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }} | |
| docker pull emersonfelipesp/proxbox-api:latest | |
| for TAG in "${{ env.IMAGE_TAG }}" latest; do | |
| docker run --rm \ | |
| -v /tmp/docker-tests.sh:/tmp/docker-tests.sh \ | |
| -v "${{ github.workspace }}/tests:/app/tests:ro" \ | |
| emersonfelipesp/proxbox-api:"$TAG" \ | |
| /tmp/docker-tests.sh | |
| done | |
| docker-mkcert: | |
| if: github.event_name == 'workflow_call' || github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && inputs.mode == 'publish') | |
| name: Docker Hub — mkcert (nginx + HTTPS + uvicorn) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.git_ref || github.event_name == 'workflow_call' && (inputs.checkout_ref != '' && inputs.checkout_ref || github.sha) || github.sha }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| # Required for cache-to: gha together with load: true (docker driver cannot export cache). | |
| driver: docker-container | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Resolve image version from pyproject | |
| id: version | |
| env: | |
| GIT_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.git_ref || github.event_name == 'workflow_call' && (inputs.checkout_ref != '' && inputs.checkout_ref || github.ref_name) || github.ref_name }} | |
| run: | | |
| python3 <<'PY' | |
| import os | |
| import pathlib | |
| import tomllib | |
| data = tomllib.loads(pathlib.Path("pyproject.toml").read_text(encoding="utf-8")) | |
| version = data["project"]["version"] | |
| expected_tag = f"v{version}" | |
| git_ref = os.environ["GIT_REF"].strip() | |
| if git_ref.startswith("v") and git_ref != expected_tag: | |
| raise SystemExit( | |
| f"git ref / pyproject mismatch: ref={git_ref!r}, expected {expected_tag!r}" | |
| ) | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh: | |
| fh.write(f"tag={version}\n") | |
| PY | |
| - name: Keep image tag in env | |
| run: echo "IMAGE_TAG=${{ steps.version.outputs.tag }}" >> $GITHUB_ENV | |
| - name: Create Docker test script | |
| run: | | |
| cat <<'EOF' > /tmp/docker-tests.sh | |
| #!/bin/sh | |
| set -eux | |
| # tests/ is bind-mounted read-only; keep bytecode out of the tree | |
| export PYTHONPYCACHEPREFIX=/tmp/pycache | |
| mkdir -p "$PYTHONPYCACHEPREFIX" | |
| export PROXBOX_SKIP_NETBOX_BOOTSTRAP=1 | |
| uv sync --frozen --extra test --group dev | |
| uv run ruff check . | |
| uv run ruff format --check . | |
| uv run python -m compileall proxbox_api scripts tests | |
| uv run python -c "import proxbox_api.main" | |
| uv run python -c "from proxbox_api.proxmox_to_netbox.proxmox_schema import load_proxmox_generated_openapi; assert load_proxmox_generated_openapi().get('paths')" | |
| uv run pytest --cov=proxbox_api --cov-report=term-missing --cov-report=xml tests --ignore=tests/e2e | |
| EOF | |
| chmod +x /tmp/docker-tests.sh | |
| - name: Build amd64 mkcert image for pre-release tests | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: mkcert | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-mkcert-pre | |
| cache-from: type=gha,scope=mkcert | |
| cache-to: type=gha,mode=max,scope=mkcert | |
| - name: Run pre-release tests in mkcert Docker image | |
| run: | | |
| docker run --rm \ | |
| -v /tmp/docker-tests.sh:/tmp/docker-tests.sh \ | |
| -v "${{ github.workspace }}/tests:/app/tests:ro" \ | |
| emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-mkcert-pre \ | |
| /tmp/docker-tests.sh | |
| - name: Build and push mkcert Docker image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| target: mkcert | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-mkcert,emersonfelipesp/proxbox-api:latest-mkcert | |
| cache-from: type=gha,scope=mkcert | |
| cache-to: type=gha,mode=max,scope=mkcert | |
| - name: Pull and verify pushed mkcert images | |
| run: | | |
| docker pull emersonfelipesp/proxbox-api:${{ env.IMAGE_TAG }}-mkcert | |
| docker pull emersonfelipesp/proxbox-api:latest-mkcert | |
| for TAG in "${{ env.IMAGE_TAG }}-mkcert" latest-mkcert; do | |
| docker run --rm \ | |
| -v /tmp/docker-tests.sh:/tmp/docker-tests.sh \ | |
| -v "${{ github.workspace }}/tests:/app/tests:ro" \ | |
| emersonfelipesp/proxbox-api:"$TAG" \ | |
| /tmp/docker-tests.sh | |
| done |