fix(ci): bound plugin-npm-release git fetch and npm publish with timeout (#110279)

* fix(ci): bound plugin-npm-release git fetch and npm publish with timeout

* fix(ci): bound plugin-npm-release git fetch and npm publish with timeout

ci: retrigger checks

* test(ci): guard plugin release timeouts

Co-authored-by: wanyongstar <wan.yong@xydigit.com>

* docs(ci): explain npm timeout recovery

Co-authored-by: wanyongstar <wan.yong@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
wanyongstar
2026-07-18 13:06:12 +08:00
committed by GitHub
parent dea1fe1f11
commit e8734d837e
2 changed files with 25 additions and 7 deletions
+9 -7
View File
@@ -131,14 +131,14 @@ jobs:
release_year="${BASH_REMATCH[1]}"
release_month="${BASH_REMATCH[2]}"
extended_stable_branch="extended-stable/${release_year}.${release_month}.33"
git fetch --no-tags origin "+refs/heads/${extended_stable_branch}:refs/remotes/origin/${extended_stable_branch}"
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags origin "+refs/heads/${extended_stable_branch}:refs/remotes/origin/${extended_stable_branch}"
if [[ "${WORKFLOW_REF}" == "refs/heads/${extended_stable_branch}" ]] && [[ "$(git rev-parse HEAD)" == "$(git rev-parse "refs/remotes/origin/${extended_stable_branch}")" ]]; then
exit 0
fi
echo "Extended-stable plugin npm publishes must run from ${extended_stable_branch} at its exact branch tip." >&2
exit 1
fi
git fetch --no-tags origin \
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags origin \
+refs/heads/main:refs/remotes/origin/main \
'+refs/heads/release/*:refs/remotes/origin/release/*'
if [[ "${PREFLIGHT_ONLY}" == "true" ]] && ! git merge-base --is-ancestor "${WORKFLOW_SHA}" origin/main; then
@@ -159,7 +159,7 @@ jobs:
fi
if [[ "${WORKFLOW_REF}" =~ ^refs/heads/tideclaw/alpha/[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{4}Z$ ]]; then
alpha_branch="${WORKFLOW_REF#refs/heads/}"
git fetch --no-tags origin "+refs/heads/${alpha_branch}:refs/remotes/origin/${alpha_branch}"
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags origin "+refs/heads/${alpha_branch}:refs/remotes/origin/${alpha_branch}"
if git merge-base --is-ancestor HEAD "refs/remotes/origin/${alpha_branch}"; then
exit 0
fi
@@ -619,7 +619,7 @@ jobs:
RUN_ATTEMPT: ${{ github.run_attempt }}
run: |
set -euo pipefail
git fetch --no-tags --depth=1 origin "${SOURCE_SHA}"
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags --depth=1 origin "${SOURCE_SHA}"
source_package_json="${RUNNER_TEMP}/${EXTENSION_ID}-source-package.json"
git show "${SOURCE_SHA}:${PACKAGE_DIR}/package.json" > "${source_package_json}"
@@ -1099,7 +1099,7 @@ jobs:
echo "npm token bootstrap requires trusted main tooling or a protected SHA-pinned release-publish tag." >&2
exit 1
}
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
git merge-base --is-ancestor "$WORKFLOW_SHA" origin/main || {
echo "npm token bootstrap workflow revision is not reachable from current main." >&2
exit 1
@@ -1137,7 +1137,7 @@ jobs:
"https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/artifacts/${artifact_id}/zip" \
-o "$artifact_zip"
git fetch --no-tags --depth=1 origin "$TARGET_SHA"
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags --depth=1 origin "$TARGET_SHA"
source_package_json="${RUNNER_TEMP}/${EXTENSION_ID}-source-package.json"
git show "${TARGET_SHA}:${PACKAGE_DIR}/package.json" > "$source_package_json"
source_package_json_sha256="$(sha256sum "$source_package_json" | awk '{print $1}')"
@@ -1321,12 +1321,14 @@ jobs:
} > "$npmrc"
chmod 0600 "$npmrc"
unset NODE_AUTH_TOKEN NPM_TOKEN NODE_OPTIONS
# A timeout can race a committed publish. On rerun, the preceding check
# accepts only this tarball's exact integrity and shasum before skipping.
HOME="$publish_home" \
NPM_CONFIG_GLOBALCONFIG=/dev/null \
NPM_CONFIG_IGNORE_SCRIPTS=true \
NPM_CONFIG_REGISTRY=https://registry.npmjs.org/ \
NPM_CONFIG_USERCONFIG="$npmrc" \
npm publish "$TARBALL_PATH" \
timeout --signal=TERM --kill-after=10s 300s npm publish "$TARBALL_PATH" \
--access public \
--ignore-scripts \
--provenance \
@@ -321,6 +321,22 @@ describe("plugin npm extended-stable workflow", () => {
expect(pluginManifest.id).toBe("meta");
});
it("bounds external git fetch and npm publish operations", () => {
const source = readFileSync(workflowPath, "utf8");
const gitFetchLines = source.split("\n").filter((line) => line.includes("git fetch"));
const npmPublishLines = source
.split("\n")
.filter((line) => line.includes('npm publish "$TARBALL_PATH"'));
expect(gitFetchLines).toHaveLength(6);
expect(
gitFetchLines.every((line) => line.includes("timeout --signal=TERM --kill-after=10s 120s")),
).toBe(true);
expect(npmPublishLines).toEqual([
' timeout --signal=TERM --kill-after=10s 300s npm publish "$TARBALL_PATH" \\',
]);
});
it("publishes extended-stable with OIDC only and verifies every package tag", () => {
const parsed = workflow();
const publish = step(parsed.jobs?.publish_plugins_npm, "Publish with trusted publisher");