diff --git a/.github/workflows/devcontainer-image.yml b/.github/workflows/devcontainer-image.yml index 4ca3dd7..f54e19c 100644 --- a/.github/workflows/devcontainer-image.yml +++ b/.github/workflows/devcontainer-image.yml @@ -20,6 +20,7 @@ jobs: build: name: Build ${{ matrix.platform }} if: github.ref == 'refs/heads/main' + environment: devcontainer-publication runs-on: ${{ matrix.runner }} timeout-minutes: ${{ matrix.timeout_minutes }} permissions: @@ -90,6 +91,7 @@ jobs: assemble: name: Assemble multi-platform image if: github.ref == 'refs/heads/main' + environment: devcontainer-publication needs: [build] runs-on: ubuntu-24.04 timeout-minutes: 5 @@ -195,6 +197,7 @@ jobs: promote: name: Publish main channel if: github.ref == 'refs/heads/main' + environment: devcontainer-publication needs: [assemble, scan, qualify] runs-on: ubuntu-24.04 timeout-minutes: 5 diff --git a/tests/Unit/DevcontainerImageContractTest.php b/tests/Unit/DevcontainerImageContractTest.php index 6fdf543..d51006d 100644 --- a/tests/Unit/DevcontainerImageContractTest.php +++ b/tests/Unit/DevcontainerImageContractTest.php @@ -219,6 +219,17 @@ public function test_main_publication_builds_both_architectures_before_promotion $this->assertStringNotContainsString('recover_revision_tag', $source); } + public function test_registry_writes_require_the_main_publication_environment(): void + { + $jobs = Yaml::parseFile($this->path('.github/workflows/devcontainer-image.yml'))['jobs']; + $writers = array_filter($jobs, static fn (array $job): bool => ($job['permissions']['packages'] ?? null) === 'write'); + $this->assertSame(['build', 'assemble', 'promote'], array_keys($writers)); + foreach ($writers as $job) { + $this->assertSame('devcontainer-publication', $job['environment'] ?? null); + $this->assertSame("github.ref == 'refs/heads/main'", $job['if']); + } + } + private function path(string $path): string { return dirname(__DIR__, 2).'/'.$path;