diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 40f851d9..5907c76e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -12,6 +12,10 @@ on: branches: [dev, main] pull_request: branches: [dev, main] + paths-ignore: + - '**.md' + - 'docs/**' + - 'LICENSE' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -24,16 +28,38 @@ env: jobs: # --------------------------------------------------------------------------- - # Stage 1: Build the image + # Stage 0: Detect what changed (drives downstream job decisions) + # --------------------------------------------------------------------------- + changes: + name: Detect changes + runs-on: ubuntu-latest + outputs: + docker_relevant: ${{ steps.filter.outputs.docker_relevant }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + docker_relevant: + - 'containers/**' + - 'Dockerfile*' + - 'pyproject.toml' + - 'requirements*.txt' + - '.dockerignore' + - '.github/workflows/docker.yml' + + # --------------------------------------------------------------------------- + # Stage 1: Build — runs on EVERY PR (cheap sanity check) # --------------------------------------------------------------------------- build: name: Build Docker image + needs: changes runs-on: ubuntu-latest outputs: image_tag: ${{ steps.determine-tag.outputs.tag }} steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - name: Determine image tag id: determine-tag @@ -43,12 +69,10 @@ jobs: else echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT fi - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # IMPROVEMENT: Added fallback cache-from to read from main branch scope. - # This ensures PRs don't start with a cold cache. - name: Build Docker image uses: docker/build-push-action@v5 with: @@ -69,7 +93,7 @@ jobs: retention-days: 1 # --------------------------------------------------------------------------- - # Stage 2: Test suite (runs in parallel after build) + # Stage 2a: Unit tests — runs on EVERY PR (cheap, ~5 min) # --------------------------------------------------------------------------- unit-test: name: Unit tests (Docker) @@ -90,37 +114,36 @@ jobs: - name: Verify MC/DC import run: | - docker run --rm mcdc:${{ needs.build.outputs.image_tag }} python -c "import mcdc; print('MC/DC import OK')" + docker run --rm mcdc:${{ needs.build.outputs.image_tag }} \ + python -c "import mcdc; print('MC/DC import OK')" - # FIX: Added isolated smoke test WITHOUT workspace mounting. - # Verifies that the built-in MC/DC code inside the image actually works. - - name: Smoke test image contents (No Mount) + - name: Smoke test image contents (no mount) run: | docker run --rm \ -w /opt/mcdc/test/unit \ mcdc:${{ needs.build.outputs.image_tag }} python run.py - # This one keeps testing PR-specific code changes via volume mount - - name: Run unit tests (With Workspace Mount) + - name: Run unit tests (with workspace mount) run: | docker run --rm \ -v ${{ github.workspace }}:/opt/mcdc \ -w /opt/mcdc/test/unit \ mcdc:${{ needs.build.outputs.image_tag }} python run.py + # --------------------------------------------------------------------------- + # Stage 2b: Regression — only on push, or on PRs touching docker-relevant files + # --------------------------------------------------------------------------- regression-test: name: Regression – ${{ matrix.mode }} - needs: build + needs: [changes, build] + if: | + github.event_name == 'push' || + needs.changes.outputs.docker_relevant == 'true' runs-on: ubuntu-latest timeout-minutes: ${{ matrix.timeout }} strategy: fail-fast: false matrix: - mode: - - Python-Serial - - Python-MPI - - Numba-Serial - - Numba-MPI include: - mode: Python-Serial run_cmd: "python run.py" @@ -128,7 +151,6 @@ jobs: - mode: Python-MPI run_cmd: | python run.py --mpiexec=4 - python run.py --mpiexec=16 --name=slab_reed_dd_3d timeout: 20 - mode: Numba-Serial run_cmd: "python run.py --mode numba" @@ -136,15 +158,13 @@ jobs: - mode: Numba-MPI run_cmd: | python run.py --mode numba --mpiexec=4 - python run.py --mode numba --mpiexec=16 --name=slab_reed_dd_3d timeout: 120 steps: - name: Checkout repository uses: actions/checkout@v4 - # FIX 1: Pull test data on host to avoid Git lock inside Docker - - name: Checkout Regression Test Data + - name: Checkout regression test data uses: actions/checkout@v4 with: repository: mcdc-project/mcdc-regression_test_data @@ -165,10 +185,13 @@ jobs: docker run --rm \ -v ${{ github.workspace }}:/opt/mcdc \ -w /opt/mcdc/test/regression \ - mcdc:${{ needs.build.outputs.image_tag }} bash -c '${{ matrix.run_cmd }}' + mcdc:${{ needs.build.outputs.image_tag }} bash -lc ' + git config --global --add safe.directory /opt/mcdc/test/regression/mcdc-regression_test_data + ${{ matrix.run_cmd }} + ' # --------------------------------------------------------------------------- - # Stage 3: Publish (only on push to dev/main, after all tests pass) + # Stage 3: Publish — only on push to dev/main, after all tests pass # --------------------------------------------------------------------------- publish: name: Publish to GHCR @@ -189,7 +212,7 @@ jobs: - name: Load Docker image run: docker load -i /tmp/mcdc-image.tar - - name: Login to GitHub Container Registry + - name: Login to GHCR uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} @@ -216,3 +239,4 @@ jobs: docker tag mcdc:${BRANCH} ${FULL_IMAGE}:latest docker push ${FULL_IMAGE}:latest fi +