mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
Switch every CI job that starts MinIO to the public `ghcr.io/block/buzz-minio:latest` image published by #7869. Integration jobs pull the image; image builds stay in the separate, path-filtered publisher workflow. - Apply the CI Compose override to both desktop integration shards, backend integration, relay E2E, and mesh lifecycle, including script-mediated Compose calls. Both the server and bucket initializer use the Buzz image. - Override both MinIO images in Helm's quickstart CI values, covering the server, bucket initializer, and relay's wait-for-bucket init container in the gated kind installation. - Select integration and mesh checks when either Compose file changes, with regression coverage using the real pinned `dorny/paths-filter` action. ### Publication verified #7869 is merged, and [the first main-branch publication](https://github.com/block/buzz/actions/runs/36021389137/job/107706874954) succeeded. An anonymous pull using an empty Docker configuration returned the publisher's digest: `sha256:b8470bbeafbf57b20c86cf63804682b714bdcfdbb517f3770247e321e623f48f`. This PR is rebased onto main and ready for consumer integration checks. ### Validation - Ran the repository's MinIO smoke script against the actual published AMD64 image: healthy startup, bucket initialization, object upload/read/delete, and rejection of anonymous reads all passed. Used the rendered CI Compose services with isolated local ports and resource names. - Verified `mc` runs and writes its configuration as Helm's non-root UID/GID 65532 with dropped capabilities and no privilege escalation. - Helm 3.16.4 lint and quickstart rendering passed; all three rendered MinIO container references use the Buzz image. - All 14 CI selection cases and the required-context isolation check passed. Mesh workflow passes actionlint; shared workflows pass with shellcheck disabled for pre-existing findings. - Fresh repository-wide review traced workflow and script consumers and found no remaining CI image omissions. Full application integration checks and a real kind installation have not been run locally. --------- Signed-off-by: Tyler Longwell <tlongwell@squareup.com>
143 lines
4.3 KiB
JavaScript
143 lines
4.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
import {
|
|
existsSync,
|
|
mkdtempSync,
|
|
mkdirSync,
|
|
readFileSync,
|
|
rmSync,
|
|
writeFileSync,
|
|
} from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { dirname, join } from "node:path";
|
|
import { after, test } from "node:test";
|
|
|
|
const workflow = readFileSync(
|
|
new URL("../.github/workflows/ci.yml", import.meta.url),
|
|
"utf8",
|
|
);
|
|
const scratch = mkdtempSync(join(tmpdir(), "buzz-ci-selection-"));
|
|
after(() => rmSync(scratch, { recursive: true, force: true }));
|
|
const actionSha = workflow.match(/uses: dorny\/paths-filter@([a-f0-9]{40})/)[1];
|
|
const filters = workflow
|
|
.match(/ {10}filters: \|\n([\s\S]*?)(?= {6}- name:)/)[1]
|
|
.split("\n")
|
|
.map((line) => line.slice(12))
|
|
.join("\n");
|
|
// GitHub-hosted runners prepare pinned actions beside RUNNER_TEMP before any
|
|
// steps run. Reuse that bundle, without another download in the selection gate.
|
|
// Locally, point PATHS_FILTER_ACTION at dist/index.js from the pinned action.
|
|
const actionPath =
|
|
process.env.PATHS_FILTER_ACTION ||
|
|
(process.env.RUNNER_TEMP &&
|
|
join(
|
|
process.env.RUNNER_TEMP,
|
|
"..",
|
|
"_actions",
|
|
"dorny",
|
|
"paths-filter",
|
|
actionSha,
|
|
"dist",
|
|
"index.js",
|
|
));
|
|
assert.ok(
|
|
actionPath && existsSync(actionPath),
|
|
`Set PATHS_FILTER_ACTION to the local dist/index.js from dorny/paths-filter@${actionSha}`,
|
|
);
|
|
function select(paths) {
|
|
const repo = mkdtempSync(join(scratch, "repo-"));
|
|
const git = (...args) =>
|
|
execFileSync("git", args, { cwd: repo, stdio: "pipe", timeout: 10000 });
|
|
git("init", "-q");
|
|
// Fixture repositories must not inherit developer machine hooks.
|
|
mkdirSync(join(repo, "empty-hooks"));
|
|
git("config", "core.hooksPath", join(repo, "empty-hooks"));
|
|
git(
|
|
"-c",
|
|
"user.name=CI fixture",
|
|
"-c",
|
|
"user.email=ci@example.com",
|
|
"-c",
|
|
"commit.gpgsign=false",
|
|
"commit",
|
|
"-q",
|
|
"--allow-empty",
|
|
"-m",
|
|
"fixture",
|
|
"-s",
|
|
);
|
|
for (const path of paths) {
|
|
mkdirSync(dirname(join(repo, path)), { recursive: true });
|
|
writeFileSync(join(repo, path), "fixture\n");
|
|
}
|
|
git("add", ".");
|
|
const output = join(repo, "action-output");
|
|
writeFileSync(output, "");
|
|
const child = spawnSync(process.execPath, [actionPath], {
|
|
cwd: repo,
|
|
encoding: "utf8",
|
|
timeout: 30000,
|
|
env: {
|
|
...process.env,
|
|
INPUT_BASE: "HEAD",
|
|
INPUT_FILTERS: filters,
|
|
INPUT_TOKEN: "",
|
|
INPUT_REF: "",
|
|
GITHUB_OUTPUT: output,
|
|
"INPUT_PREDICATE-QUANTIFIER":
|
|
workflow.match(/predicate-quantifier: ['"]?([\w-]+)/)?.[1] ?? "some",
|
|
},
|
|
});
|
|
assert.equal(child.status, 0, child.stdout + child.stderr);
|
|
return Object.fromEntries(
|
|
[
|
|
...readFileSync(output, "utf8").matchAll(
|
|
/^(rust|desktop|desktop-rust|web|mobile)<<([^\n]+)\n(true|false)\n\2/gm,
|
|
),
|
|
].map(([, key, , value]) => [key, value]),
|
|
);
|
|
}
|
|
const scenarios = [
|
|
[
|
|
"mobile source and tests",
|
|
[
|
|
"mobile/lib/features/age_gate/age_signal_provider.dart",
|
|
"mobile/test/features/age_gate/age_signal_provider_test.dart",
|
|
],
|
|
["mobile"],
|
|
],
|
|
["mobile lockfile", ["mobile/pubspec.lock"], ["mobile"]],
|
|
["mobile release script", ["scripts/mobile-release.sh"], ["mobile"]],
|
|
["desktop", ["desktop/src/main.tsx"], ["desktop"]],
|
|
["Tauri", ["desktop/src-tauri/src/main.rs"], ["desktop", "desktop-rust"]],
|
|
["relay", ["crates/buzz-relay/src/main.rs"], ["rust"]],
|
|
["migration", ["migrations/123.sql"], ["rust"]],
|
|
["shared workflow", [".github/workflows/ci.yml"], ["rust", "mobile"]],
|
|
["integration services", ["docker-compose.yml"], ["rust"]],
|
|
["CI integration images", ["docker-compose.ci.yml"], ["rust"]],
|
|
[
|
|
"mixed mobile and relay",
|
|
["mobile/lib/main.dart", "crates/buzz-core/src/lib.rs"],
|
|
["rust", "mobile"],
|
|
],
|
|
[
|
|
"mixed mobile and desktop",
|
|
["mobile/lib/main.dart", "desktop/src/main.tsx"],
|
|
["desktop", "mobile"],
|
|
],
|
|
["web", ["web/src/main.tsx"], ["web"]],
|
|
["documentation", ["README.md"], []],
|
|
];
|
|
for (const [name, paths, expected] of scenarios) {
|
|
test(`real paths-filter: ${name}`, () => {
|
|
const outputs = select(paths);
|
|
assert.equal(Object.keys(outputs).length, 5);
|
|
assert.deepEqual(
|
|
Object.keys(outputs)
|
|
.filter((key) => outputs[key] === "true")
|
|
.sort(),
|
|
expected.sort(),
|
|
);
|
|
});
|
|
}
|