diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 992f6f4..7469df8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,12 +165,12 @@ jobs: # packages, and verifies. Nothing is published and no credential exists here. A future publish # job must depend on this job and publish only the artifacts it proved. - name: Build, reproduce, and consume the public package train - run: pnpm test:package-release --keep .package-release + run: pnpm test:package-release --keep package-train - name: Describe the proven release train id: release run: | - release="$(find .package-release -mindepth 1 -maxdepth 1 -type d)" + release="$(find package-train -mindepth 1 -maxdepth 1 -type d)" manifest="$release/ekklesia-package-train.json" { echo "version=$(node -p 'JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")).version' "$manifest")" @@ -179,14 +179,15 @@ jobs: } >>"$GITHUB_OUTPUT" cat "$manifest" - # The exact release artifacts, for the jobs that consume them. Version 3 of the artifact + # The exact release artifacts, for the jobs that consume them, from a directory whose name does + # not start with a dot: the artifact actions leave hidden files out. Version 3 of the artifact # actions: version 4 refuses any server that is not github.com, which this Gitea is not, while # Gitea implements the protocol version 3 uses. A consumer checks the files, not the wrapper. - name: Hand the release train on uses: actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de # v3.2.2-node20 with: name: package-train - path: .package-release/ + path: package-train/ if-no-files-found: error retention-days: 7 @@ -228,13 +229,13 @@ jobs: uses: actions/download-artifact@ad191675b41f6a5b46da9a048cb6893812da158b # v3.1.0-node20 with: name: package-train - path: .package-release/ + path: package-train/ - name: Check it is exactly that train env: EXPECTED_MANIFEST_SHA256: ${{ needs.package-release.outputs.manifest_sha256 }} run: | - release="$(find .package-release -mindepth 1 -maxdepth 1 -type d)" + release="$(find package-train -mindepth 1 -maxdepth 1 -type d)" actual="$(sha256sum "$release/ekklesia-package-train.json" | cut -d' ' -f1)" if [[ -z "$EXPECTED_MANIFEST_SHA256" || "$actual" != "$EXPECTED_MANIFEST_SHA256" ]]; then echo "The received release manifest is not the one the package-release job proved." >&2 @@ -243,7 +244,7 @@ jobs: (cd "$release" && sha256sum --check --strict SHA256SUMS) - name: Publish it to a disposable Gitea, and prove the round trip and recovery - run: bash scripts/test-package-publication.sh --release "$(find .package-release -mindepth 1 -maxdepth 1 -type d)" + run: bash scripts/test-package-publication.sh --release "$(find package-train -mindepth 1 -maxdepth 1 -type d)" # Whatever happened above, this job's own stacks do not outlive it. - name: Remove this job's CI stacks diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index ebdb113..540375d 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -59,12 +59,12 @@ jobs: # The same credential-free gate as CI: build, reproduce, and consume the train. - name: Build, reproduce, and consume the public package train - run: pnpm test:package-release --keep .package-release + run: pnpm test:package-release --keep package-train - name: Describe the proven release train id: release run: | - release="$(find .package-release -mindepth 1 -maxdepth 1 -type d)" + release="$(find package-train -mindepth 1 -maxdepth 1 -type d)" manifest="$release/ekklesia-package-train.json" { echo "version=$(node -p 'JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")).version' "$manifest")" @@ -72,12 +72,13 @@ jobs: echo "manifest_sha256=$(sha256sum "$manifest" | cut -d' ' -f1)" } >>"$GITHUB_OUTPUT" - # Artifact actions version 3: version 4 refuses any server that is not github.com. + # Artifact actions version 3: version 4 refuses any server that is not github.com. The directory + # name must not start with a dot: the artifact actions leave hidden files out. - name: Hand the release train on uses: actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de # v3.2.2-node20 with: name: package-train - path: .package-release/ + path: package-train/ if-no-files-found: error retention-days: 90 @@ -102,7 +103,7 @@ jobs: uses: actions/download-artifact@ad191675b41f6a5b46da9a048cb6893812da158b # v3.1.0-node20 with: name: package-train - path: .package-release/ + path: package-train/ # The tool validates the whole train against its manifest, that manifest against the gate's, # its version against the request, and its revision against this commit, before it sends @@ -115,7 +116,7 @@ jobs: MANIFEST_SHA256: ${{ needs.package-release.outputs.manifest_sha256 }} run: | node scripts/publish-package-train.ts \ - --release "$(find .package-release -mindepth 1 -maxdepth 1 -type d)" \ + --release "$(find package-train -mindepth 1 -maxdepth 1 -type d)" \ --registry "$EKKLESIA_PACKAGES_REGISTRY" \ --version "$TRAIN_VERSION" \ --revision "$TRAIN_REVISION" \ diff --git a/.gitignore b/.gitignore index be58ca3..cf6133f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ packages/module-pack/.fixtures/ # `pnpm packages:release` writes package release trains here (scripts/package-release.ts). .package-release/ +# CI keeps the proven release here to hand it on as a workflow artifact (scripts/test-package-release.sh --keep). +/package-train/ diff --git a/tests/package-publication.test.ts b/tests/package-publication.test.ts index 4394775..988bead 100644 --- a/tests/package-publication.test.ts +++ b/tests/package-publication.test.ts @@ -531,12 +531,16 @@ describe("when the real registry can be written to", () => { expect(publishRuns).not.toMatch(/pnpm|npm (?:install|ci|run|pack)|package-release\.ts/u); }); - it("uses the artifact actions that work on this Gitea, pinned by commit", async () => { + it("uses the artifact actions that work on this Gitea, pinned by commit, on visible paths", async () => { for (const file of ["ci.yml", "publish-packages.yml"]) { const text = await readFile(path.join(repositoryRoot, ".github/workflows", file), "utf8"); for (const use of text.matchAll(/uses: (actions\/(?:up|down)load-artifact)@(\S+)/gu)) { expect(use[2], `${file} ${use[1]}`).toMatch(/^[0-9a-f]{40}$/u); } + // The artifact actions leave hidden files out: a path starting with a dot uploads nothing. + for (const artifactPath of text.matchAll(/^\s+path: (\S+)$/gmu)) { + expect(artifactPath[1], file).not.toMatch(/^\.|\/\./u); + } } }); });