refactor(ci): inline container build into integration workflow

Build the Docker image as a job within the integration workflow rather
than a separate workflow. This ensures the container always matches the
current commit's Dockerfile. Tag with github.sha so the integration job
pulls the exact image, not a stale latest.

- container-image job: builds and pushes to GHCR with sha + latest tags
- integration job: uses credentials: to pull private image on self-hosted
- Delete standalone build-test-container.yml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Clint Branham
2026-03-19 11:49:27 -05:00
parent f1583b4c6c
commit c4cd9bc60d
2 changed files with 39 additions and 53 deletions
@@ -1,42 +0,0 @@
name: Build Integration Test Container
on:
push:
branches: [ main ]
paths:
- 'tests/infrastructure/Dockerfile'
- '.github/workflows/build-test-container.yml'
workflow_dispatch:
permissions:
contents: read
packages: write
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/psproxmoxve-integration:latest
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v5
- name: Lowercase image name
id: image
run: echo "name=${IMAGE,,}" >> "$GITHUB_OUTPUT"
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v7
with:
context: tests/infrastructure
file: tests/infrastructure/Dockerfile
push: true
tags: ${{ steps.image.outputs.name }}
+39 -11
View File
@@ -1,13 +1,11 @@
name: Integration Tests name: Integration Tests
# Real integration tests against a live Proxmox VE instance. # Real integration tests against a live Proxmox VE instance.
# By default, provisions throwaway nested PVE VMs via Terraform for both
# PVE 8 and PVE 9, runs tests against each, then destroys them.
# Can also run against a pre-existing PVE with skip_provision.
# #
# Architecture: # Architecture:
# build job → GitHub-hosted runner, dotnet publish → upload artifact # build → GitHub-hosted, dotnet publish → upload artifact
# integration → self-hosted runner in Docker container, downloads artifact # container-image → GitHub-hosted, build+push Docker image to GHCR
# integration → self-hosted runner in Docker container
# #
# Required repository secrets (for provisioning): # Required repository secrets (for provisioning):
# PVE_ENDPOINT - Parent PVE API URL (e.g. https://pve.example.com:8006) # PVE_ENDPOINT - Parent PVE API URL (e.g. https://pve.example.com:8006)
@@ -18,8 +16,8 @@ name: Integration Tests
# PVETEST_HOST - Hostname or IP of a pre-existing nested PVE # PVETEST_HOST - Hostname or IP of a pre-existing nested PVE
# PVETEST_APITOKEN - API token for the pre-existing nested PVE # PVETEST_APITOKEN - API token for the pre-existing nested PVE
# #
# WARNING: Integration tests create and destroy real resources (VMs, users, # WARNING: Integration tests create and destroy real resources on the target
# tokens, network config, etc.) on the target node. Never run against production. # node. Never run against production.
on: on:
push: push:
@@ -34,13 +32,18 @@ on:
type: boolean type: boolean
default: false default: false
permissions:
contents: read
packages: write
env: env:
INFRA_DIR: tests/infrastructure INFRA_DIR: tests/infrastructure
SCRIPTS_DIR: tests/infrastructure/scripts SCRIPTS_DIR: tests/infrastructure/scripts
PVE_PASSWORD: "Testpass123!" PVE_PASSWORD: "Testpass123!"
TEST_IMAGE: ghcr.io/goodolclint/psproxmoxve-integration
jobs: jobs:
# ── Build module artifact (GitHub-hosted, no .NET SDK in container) ── # ── Build module artifact (GitHub-hosted) ────────────────────────────
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
@@ -64,13 +67,38 @@ jobs:
name: module-integration name: module-integration
path: ./publish/netstandard2.0/ path: ./publish/netstandard2.0/
# ── Build test container image (GitHub-hosted) ───────────────────────
container-image:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v5
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v7
with:
context: tests/infrastructure
file: tests/infrastructure/Dockerfile
push: true
tags: ${{ env.TEST_IMAGE }}:${{ github.sha }},${{ env.TEST_IMAGE }}:latest
# ── Integration tests (self-hosted runner in Docker container) ─────── # ── Integration tests (self-hosted runner in Docker container) ───────
integration: integration:
needs: build needs: [build, container-image]
runs-on: [self-hosted, proxmox, integration] runs-on: [self-hosted, proxmox, integration]
timeout-minutes: 45 timeout-minutes: 45
container: container:
image: ghcr.io/goodolclint/psproxmoxve-integration:latest image: ghcr.io/goodolclint/psproxmoxve-integration:${{ github.sha }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
volumes: volumes:
- /opt/pve-isos:/opt/pve-isos - /opt/pve-isos:/opt/pve-isos
- /opt/pve-images:/opt/pve-images - /opt/pve-images:/opt/pve-images
@@ -218,7 +246,7 @@ jobs:
# ── Prepare test Linux VM ──────────────────────────────────────── # ── Prepare test Linux VM ────────────────────────────────────────
- name: Build Alpine test image (cached on host) - name: Build Alpine test image (cached on host volume)
if: inputs.skip_provision != true if: inputs.skip_provision != true
shell: bash shell: bash
run: | run: |