mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
ci: dispatch required checks for catalog publication (#4345)
This commit is contained in:
@@ -6,6 +6,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ env:
|
||||
HYPERFRAMES_NO_TELEMETRY: "1"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
# `edited` is required so the workflow re-fires when a PR's base ref is
|
||||
# set back to `main` after a Graphite stack restack momentarily flips
|
||||
@@ -56,7 +57,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
outputs:
|
||||
code: ${{ steps.filter.outputs.code }}
|
||||
code: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.code == 'true' }}
|
||||
docs_catalog: ${{ steps.filter.outputs.docs_catalog }}
|
||||
cli: ${{ steps.filter.outputs.cli }}
|
||||
skills: ${{ steps.filter.outputs.skills }}
|
||||
@@ -232,7 +233,7 @@ jobs:
|
||||
run: node scripts/check-catalog-source-pr.mjs origin/main
|
||||
- name: Generate and validate catalog
|
||||
env:
|
||||
PUBLISH_PR: ${{ github.head_ref == 'bot/catalog-publish' }}
|
||||
PUBLISH_PR: ${{ (github.head_ref || github.ref_name) == 'bot/catalog-publish' }}
|
||||
run: |
|
||||
if [ "$PUBLISH_PR" = "true" ]; then
|
||||
bun run check:catalog-drift --committed
|
||||
@@ -1062,15 +1063,31 @@ jobs:
|
||||
|
||||
semantic-pr-title:
|
||||
name: Semantic PR title
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # v5
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
- id: pr
|
||||
run: node scripts/ci/resolve-workflow-pr.mjs
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
repository: amannn/action-semantic-pull-request
|
||||
ref: e32d7e603df1aa1ba07e981f2a23455dee596825 # v5
|
||||
path: .semantic-pr-action
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: 22
|
||||
- name: Validate PR title
|
||||
run: GITHUB_EVENT_PATH="$PR_EVENT_PATH" node .semantic-pr-action/dist/index.js
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
types: |
|
||||
PR_EVENT_PATH: ${{ steps.pr.outputs.event_path }}
|
||||
INPUT_GITHUBBASEURL: ${{ github.api_url }}
|
||||
INPUT_TYPES: |
|
||||
feat
|
||||
fix
|
||||
docs
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
name: CodeQL
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
@@ -6,12 +6,13 @@ permissions:
|
||||
|
||||
# Runs on every PR (no path filter) so it can be a required check; the script passes when neither package changed.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
branches: [main]
|
||||
|
||||
concurrency:
|
||||
group: pr-captures-${{ github.event.pull_request.number }}
|
||||
group: pr-captures-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -23,12 +24,16 @@ jobs:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: pr
|
||||
run: node scripts/ci/resolve-workflow-pr.mjs
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Require Before and After captures
|
||||
env:
|
||||
PR_BODY: ${{ github.event.pull_request.body }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
||||
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
PR_BODY: ${{ fromJSON(steps.pr.outputs.pr).body }}
|
||||
PR_NUMBER: ${{ fromJSON(steps.pr.outputs.pr).number }}
|
||||
BASE_REF: ${{ fromJSON(steps.pr.outputs.pr).base.ref }}
|
||||
HEAD_REPO: ${{ fromJSON(steps.pr.outputs.pr).head.repo.full_name }}
|
||||
BASE_REPO: ${{ github.repository }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
HEAD_SHA: ${{ fromJSON(steps.pr.outputs.pr).head.sha }}
|
||||
run: node scripts/check-pr-captures.mjs --base "origin/$BASE_REF" --head "$HEAD_SHA"
|
||||
|
||||
@@ -15,6 +15,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
# Re-run when Graphite changes only the PR base for the same head SHA.
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
@@ -28,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
outputs:
|
||||
code: ${{ steps.filter.outputs.code }}
|
||||
code: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.code == 'true' }}
|
||||
matrix: ${{ steps.shards.outputs.matrix }}
|
||||
steps:
|
||||
# Force git-based change detection instead of the pull_request REST API.
|
||||
|
||||
@@ -30,7 +30,7 @@ on:
|
||||
ref:
|
||||
description: "Git ref to render (branch / tag / SHA)."
|
||||
required: false
|
||||
default: "main"
|
||||
default: ""
|
||||
|
||||
concurrency:
|
||||
group: windows-render-${{ github.ref }}
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
ref: ${{ inputs.ref || github.sha }}
|
||||
- uses: ./.github/actions/preflight
|
||||
|
||||
render-windows:
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
ref: ${{ inputs.ref || github.sha }}
|
||||
lfs: true
|
||||
|
||||
- name: Show platform info
|
||||
@@ -416,7 +416,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
ref: ${{ inputs.ref || github.sha }}
|
||||
lfs: true
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@
|
||||
"player:perf": "bun run --filter @hyperframes/player perf",
|
||||
"format:check": "oxfmt --check .",
|
||||
"knip": "knip",
|
||||
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
|
||||
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
|
||||
"typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json",
|
||||
"test:skills": "node --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'",
|
||||
"generate:previews": "tsx scripts/generate-template-previews.ts",
|
||||
|
||||
@@ -82,7 +82,7 @@ test("oversized API files fail before any publication", () => {
|
||||
);
|
||||
});
|
||||
|
||||
function publicationFixture(t, changed) {
|
||||
function publicationFixture(t, changed, apiEnv = {}) {
|
||||
const root = mkdtempSync(join(tmpdir(), "catalog-publication-api-"));
|
||||
t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||
const git = (...args) => execFileSync("git", args, { cwd: root, encoding: "utf8" }).trim();
|
||||
@@ -116,11 +116,14 @@ const endpoint = args[1];
|
||||
const method = args[args.indexOf("--method") + 1];
|
||||
const body = args.includes("--input") ? JSON.parse(fs.readFileSync(0, "utf8")) : undefined;
|
||||
fs.appendFileSync(process.env.API_CALLS, JSON.stringify({ endpoint, method, body }) + "\\n");
|
||||
if (endpoint === "graphql" || method === "DELETE") {
|
||||
if (!process.env.PUBLISH_SUCCESS && (endpoint === "graphql" || method === "DELETE")) {
|
||||
console.error(endpoint === "graphql" ? "commit rejected" : "cleanup rejected");
|
||||
process.exit(1);
|
||||
}
|
||||
if (endpoint.endsWith("/ref/heads/main")) console.log(process.env.BASE);
|
||||
if (endpoint === "graphql") console.log("c".repeat(40));
|
||||
else if (endpoint.includes("/runs?")) console.log(JSON.stringify({ workflow_runs: JSON.parse(process.env.WORKFLOW_RUNS || "[]") }));
|
||||
else if (endpoint.endsWith("/dispatches") && process.env.DISPATCH_FAIL) process.exit(1);
|
||||
else if (endpoint.endsWith("/ref/heads/main")) console.log(process.env.BASE);
|
||||
else if (endpoint.includes("/matching-refs/")) console.log("refs/heads/bot/catalog-publish");
|
||||
else if (endpoint.includes("/ref/heads/bot/catalog-publish")) console.log("a".repeat(40));
|
||||
else if (endpoint.includes("/commits/")) console.log("b".repeat(40));
|
||||
@@ -155,6 +158,7 @@ catch (error) {
|
||||
GITHUB_REPOSITORY: "test/catalog",
|
||||
GITHUB_RUN_ID: "123",
|
||||
GITHUB_RUN_ATTEMPT: "1",
|
||||
...apiEnv,
|
||||
},
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
},
|
||||
@@ -213,3 +217,34 @@ test("publication refuses symlinks instead of reading outside the generated arti
|
||||
symlinkSync(unrelated, artifact);
|
||||
assert.throws(() => catalogChanges(fixture.root, "HEAD"), /ELOOP|symbolic link/);
|
||||
});
|
||||
|
||||
test("publication dispatches every required workflow after updating its branch and PR", (t) => {
|
||||
const fixture = publicationFixture(t, true, { PUBLISH_SUCCESS: "1" });
|
||||
fixture.run();
|
||||
const calls = fixture.calls();
|
||||
const dispatches = calls.filter((call) => call.endpoint.endsWith("/dispatches"));
|
||||
assert.deepEqual(
|
||||
dispatches.map((call) => call.endpoint.split("/").at(-2)),
|
||||
["ci.yml", "regression.yml", "windows-render.yml", "pr-captures.yml", "codeql.yml"],
|
||||
);
|
||||
for (const call of dispatches) assert.deepEqual(call.body, { ref: "bot/catalog-publish" });
|
||||
assert.ok(
|
||||
calls.indexOf(dispatches[0]) >
|
||||
calls.findIndex((call) => call.endpoint.endsWith("/pulls/42") && call.method === "PATCH"),
|
||||
);
|
||||
});
|
||||
|
||||
test("publication leaves existing successful workflows at the same head alone", (t) => {
|
||||
const fixture = publicationFixture(t, true, {
|
||||
PUBLISH_SUCCESS: "1",
|
||||
WORKFLOW_RUNS: JSON.stringify([{ status: "completed", conclusion: "success" }]),
|
||||
});
|
||||
fixture.run();
|
||||
assert.equal(fixture.calls().filter((call) => call.endpoint.endsWith("/dispatches")).length, 0);
|
||||
});
|
||||
|
||||
test("dispatch rejection fails publication and still cleans up the staging branch", (t) => {
|
||||
const fixture = publicationFixture(t, true, { PUBLISH_SUCCESS: "1", DISPATCH_FAIL: "1" });
|
||||
assert.throws(fixture.run);
|
||||
assert.equal(fixture.calls().at(-1).method, "DELETE");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { appendFileSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
|
||||
export function dispatchedPullRequest(pulls, repository, branch, sha) {
|
||||
const matches = pulls.filter(
|
||||
(pr) => pr.state === "open" && pr.head.repo?.full_name === repository && pr.head.ref === branch,
|
||||
);
|
||||
if (matches.length !== 1)
|
||||
throw new Error("Dispatch requires exactly one open PR for this branch.");
|
||||
const pr = matches[0];
|
||||
if (pr.head.sha !== sha)
|
||||
throw new Error("PR head changed after dispatch; run checks on the new head.");
|
||||
return pr;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const event = JSON.parse(readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"));
|
||||
if (process.env.GITHUB_EVENT_NAME === "workflow_dispatch") {
|
||||
const repository = process.env.GITHUB_REPOSITORY;
|
||||
const branch = process.env.GITHUB_REF_NAME;
|
||||
const owner = repository.split("/")[0];
|
||||
const raw = execFileSync(
|
||||
"gh",
|
||||
[
|
||||
"api",
|
||||
`repos/${repository}/pulls?state=open&head=${encodeURIComponent(`${owner}:${branch}`)}&per_page=100`,
|
||||
],
|
||||
{ encoding: "utf8", timeout: 60_000 },
|
||||
);
|
||||
event.pull_request = dispatchedPullRequest(
|
||||
JSON.parse(raw),
|
||||
repository,
|
||||
branch,
|
||||
process.env.GITHUB_SHA,
|
||||
);
|
||||
}
|
||||
if (!event.pull_request) throw new Error("This check requires an open pull request.");
|
||||
const path = join(process.env.RUNNER_TEMP, "workflow-pr-event.json");
|
||||
writeFileSync(path, JSON.stringify(event));
|
||||
appendFileSync(
|
||||
process.env.GITHUB_OUTPUT,
|
||||
`event_path=${path}\npr=${JSON.stringify(event.pull_request)}\n`,
|
||||
);
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) main();
|
||||
@@ -0,0 +1,27 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
import { dispatchedPullRequest } from "./resolve-workflow-pr.mjs";
|
||||
|
||||
const pr = {
|
||||
state: "open",
|
||||
number: 7,
|
||||
head: { repo: { full_name: "owner/repo" }, ref: "bot/catalog-publish", sha: "a".repeat(40) },
|
||||
};
|
||||
const resolve = (pulls, sha = pr.head.sha) =>
|
||||
dispatchedPullRequest(pulls, "owner/repo", pr.head.ref, sha);
|
||||
|
||||
test("uses the PR for the dispatched repository, branch and exact head", () => {
|
||||
assert.equal(
|
||||
resolve([{ ...pr, head: { ...pr.head, repo: { full_name: "fork/repo" } } }, pr]),
|
||||
pr,
|
||||
);
|
||||
});
|
||||
test("refuses a dispatch without an open PR", () => {
|
||||
assert.throws(() => resolve([{ ...pr, state: "closed" }]), /exactly one/);
|
||||
});
|
||||
test("refuses ambiguous PRs", () => {
|
||||
assert.throws(() => resolve([pr, { ...pr, number: 8 }]), /exactly one/);
|
||||
});
|
||||
test("refuses a PR which advanced after dispatch", () => {
|
||||
assert.throws(() => resolve([pr], "b".repeat(40)), /head changed/);
|
||||
});
|
||||
@@ -177,7 +177,7 @@ function openPublishPr(repository, base) {
|
||||
const body =
|
||||
`Generated catalog snapshot from ${base}.\n\n` +
|
||||
"Item sources are reviewed in their own PRs. This PR publishes the registry index, search vectors, docs pages, payloads and navigation together.\n\n" +
|
||||
"Approve any GitHub Actions runs awaiting approval, then review and merge this PR after checks pass. Publication uses GITHUB_TOKEN and GitHub-signed API commits; branch protection remains in effect.";
|
||||
"Required workflows are dispatched on this snapshot. Review and merge after checks pass. Publication uses GITHUB_TOKEN and GitHub-signed API commits; branch protection remains in effect.";
|
||||
if (number !== undefined) {
|
||||
if (api(`${endpoint}/${number}`, "GET", undefined, ".body") !== body)
|
||||
api(`${endpoint}/${number}`, "PATCH", { title: TITLE, body });
|
||||
@@ -186,6 +186,31 @@ function openPublishPr(repository, base) {
|
||||
}
|
||||
}
|
||||
|
||||
function checkAlreadyScheduled(run) {
|
||||
if (!run) return false;
|
||||
return run.status !== "completed" || run.conclusion === "success";
|
||||
}
|
||||
|
||||
function dispatchPublishChecks(repository) {
|
||||
const head = commitOid(
|
||||
api(`repos/${repository}/git/ref/heads/${BRANCH}`, "GET", undefined, ".object.sha"),
|
||||
);
|
||||
for (const workflow of [
|
||||
"ci.yml",
|
||||
"regression.yml",
|
||||
"windows-render.yml",
|
||||
"pr-captures.yml",
|
||||
"codeql.yml",
|
||||
]) {
|
||||
const endpoint = `repos/${repository}/actions/workflows/${workflow}`;
|
||||
const runs = JSON.parse(
|
||||
api(`${endpoint}/runs?event=workflow_dispatch&head_sha=${head}&per_page=1`),
|
||||
);
|
||||
if (checkAlreadyScheduled(runs.workflow_runs[0])) continue;
|
||||
api(`${endpoint}/dispatches`, "POST", { ref: BRANCH });
|
||||
}
|
||||
}
|
||||
|
||||
function actionEnvironment() {
|
||||
const { GITHUB_REPOSITORY: repository = "", GITHUB_RUN_ID: run = "" } = process.env;
|
||||
if (!/^[\w.-]+\/[\w.-]+$/.test(repository) || !/^\d+$/.test(run))
|
||||
@@ -245,6 +270,7 @@ function publishSnapshot(context, base, exists, batches) {
|
||||
assertCurrentMain(endpoint, base);
|
||||
updateStandingBranch(endpoint, exists, head);
|
||||
openPublishPr(repository, base);
|
||||
dispatchPublishChecks(repository);
|
||||
} catch (error) {
|
||||
errors.push(error);
|
||||
}
|
||||
@@ -269,6 +295,7 @@ export function publish(root) {
|
||||
if (batches.length === 0) return clearObsoletePublication(repository, base, exists);
|
||||
if (snapshotMatches(root, endpoint, exists)) {
|
||||
openPublishPr(repository, base);
|
||||
dispatchPublishChecks(repository);
|
||||
console.log("Standing catalog PR already contains this snapshot.");
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user