Skip to content

chore(ci-governance): synchronize Node profile - #23

Open
inditextechci-sync[bot] wants to merge 2 commits into
developfrom
automated/ci-governance-sync
Open

inditextechci-sync[bot] wants to merge 2 commits into
developfrom
automated/ci-governance-sync

Conversation

@inditextechci-sync

@inditextechci-sync inditextechci-sync Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

CI governance synchronization

This PR was generated by the PR-only controller. Review and merge it; the controller never pushes directly to the default branch.

Profile

  • node (Node)

Source revisions

  • base: 614b384ab7cc1c9111bafafe76ed5d2c22809486
  • node: 2169182171a0c208ba36bac34ccc41e618126f12

Planned changes

  • update .github/inditextech-ci-sync-manifest.json
  • update .github/workflows/code-npm_node-PR_verify.yml
  • update .github/workflows/code-npm_node-publish-release-and-snapshot.yml
  • update .github/workflows/code-npm_node-release-core.yml
  • update .github/workflows/code-npm_node-sonarcloud-analysis.yml
  • update .github/workflows/code-release_preview.yml
  • update .github/workflows/codeql.yml
  • update .github/workflows/pr-verify.yml
  • update .github/workflows/push-verify.yml
  • add .github/workflows/scorecard-analysis.yml
  • update .github/workflows/sync-to-develop.yml

Governance-Provenance: hmac-sha256:0837805e11b99a61122d875508937baaf8f6e7ea3020166fd7d18275ddf05021
@inditextechci-sync
inditextechci-sync Bot requested a review from a team as a code owner September 18, 2026 02:34
@inditextechci-sync inditextechci-sync Bot added the skip-release Do not publish a release for this change. label Sep 18, 2026
Comment on lines +739 to +963
env:
HANDOFF_DIR: ${{ runner.temp }}/node-delegated-release-handoff
RELEASES: ${{ steps.delegated-plan.outputs.releases_intermediate }}
working-directory: ${{ env.WORKING_DIRECTORY }}
shell: bash
run: |
set -euo pipefail
DIST_DIR="$HANDOFF_DIR/tarballs"
RECORDS_FILE="$HANDOFF_DIR/tarballs.jsonl"
rm -rf "$HANDOFF_DIR"
mkdir -p "$DIST_DIR"
: > "$RECORDS_FILE"

inspect_declared_files() {
local package_dir="$1"
local tarball="$2"
local manifest="$package_dir/package.json"
local declared matched path relative
jq -e '
.files
| type == "array" and length > 0 and
all(.[]; type == "string" and length > 0 and test("^[^\\r\\n]+$"))
' "$manifest" > /dev/null
while IFS= read -r declared; do
if [[ "$declared" == /* || "$declared" == "." || "$declared" == ".." || "$declared" == ../* || "$declared" == */../* || "$declared" == */.. || "$declared" == "!"* || "$declared" == *"{"* || "$declared" == *"}"* || "$declared" == *\\* || "$declared" == *"@("* || "$declared" == *"+("* || "$declared" == *"?("* || "$declared" == *"*("* || "$declared" == *"!("* ]]; then
echo "::error title=Unsupported package contents declaration::${manifest} declares an unsafe or unverifiable pattern '$declared'."
exit 1
fi
matched=0
if [[ "$declared" == *"*"* || "$declared" == *"?"* || "$declared" == *"["* || "$declared" == *"]"* ]]; then
while IFS= read -r -d '' path; do
relative="${path#"$package_dir"/}"
matched=$((matched + 1))
if ! tar -tzf "$tarball" | grep -qxF "package/$relative"; then
echo "::error title=Incomplete tarball::$(basename "$tarball") omits declared file '$relative'."
exit 1
fi
done < <(node - "$package_dir" "$declared" <<'NODE'
const fs = require("fs");
const path = require("path");
const root = process.argv[2];
const pattern = process.argv[3];
let expression = "^";
for (let index = 0; index < pattern.length; index += 1) {
const character = pattern[index];
if (character === "*") {
let stars = 1;
while (pattern[index + stars] === "*") stars += 1;
if (stars > 1 && pattern[index + stars] === "/") {
expression += "(?:[^/]+/)*";
index += stars;
} else {
expression += stars > 1 ? ".*" : "[^/]*";
index += stars - 1;
}
} else if (character === "?") {
expression += "[^/]";
} else if (character === "[") {
const closing = pattern.indexOf("]", index + 1);
if (closing === -1 || closing === index + 1) process.exit(2);
const characterClass = pattern.slice(index + 1, closing);
if (characterClass.includes("/") || characterClass.includes("\\")) process.exit(2);
expression += `[${characterClass[0] === "!" ? "^" + characterClass.slice(1) : characterClass}]`;
index = closing;
} else if (character === "]") {
process.exit(2);
} else {
expression += character.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
}
}
const matcher = new RegExp(`${expression}$`);
const files = [];
const walk = (directory) => {
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const candidate = path.join(directory, entry.name);
if (entry.isDirectory()) walk(candidate);
else if (entry.isFile()) files.push(path.relative(root, candidate).split(path.sep).join("/"));
}
};
walk(root);
for (const file of files.filter((file) => matcher.test(file)).sort()) process.stdout.write(`${path.join(root, file)}\0`);
NODE
)
elif [[ -d "$package_dir/$declared" ]]; then
while IFS= read -r -d '' path; do
relative="${path#"$package_dir"/}"
matched=$((matched + 1))
if ! tar -tzf "$tarball" | grep -qxF "package/$relative"; then
echo "::error title=Incomplete tarball::$(basename "$tarball") omits declared file '$relative'."
exit 1
fi
done < <(find "$package_dir/$declared" -type f -print0)
elif [[ -f "$package_dir/$declared" ]]; then
matched=1
if ! tar -tzf "$tarball" | grep -qxF "package/$declared"; then
echo "::error title=Incomplete tarball::$(basename "$tarball") omits declared file '$declared'."
exit 1
fi
fi
if [[ "$matched" -eq 0 ]]; then
echo "::error title=Missing declared package content::${manifest} declaration '$declared' matches no built files."
exit 1
fi
done < <(jq -r '.files[]' "$manifest")
}

release_tag_for() {
local package_name="$1"
local package_version="$2"
local member record release_tag release_version
local -a exact_matches=()
local -a version_matches=()
member="$(printf '%s' "${package_name##*/}" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//')"
while IFS= read -r record; do
release_tag="$(jq -r '.tag' <<< "$record")"
release_version="$(jq -r '.version' <<< "$record")"
[[ "$release_version" == "$package_version" ]] || continue
version_matches+=("$release_tag")
if [[ "$release_tag" == "$package_version" || "$release_tag" == "${member}-${package_version}" || "$release_tag" == "${package_name}-${package_version}" ]]; then
exact_matches+=("$release_tag")
fi
done < <(jq -c '.[]' <<< "$RELEASES")
if [[ ${#exact_matches[@]} -eq 1 ]]; then
printf '%s' "${exact_matches[0]}"
elif [[ ${#exact_matches[@]} -eq 0 && ${#version_matches[@]} -eq 1 ]]; then
printf '%s' "${version_matches[0]}"
else
echo "::error title=Ambiguous package release::Package '$package_name@$package_version' does not resolve to exactly one prepared release tag." >&2
exit 1
fi
}

pack_package() {
local package_dir="$1"
local package_name="$2"
local before="$HANDOFF_DIR/tarballs-before.txt"
local after="$HANDOFF_DIR/tarballs-after.txt"
local added="$HANDOFF_DIR/tarballs-added.txt"
local tarball
find "$DIST_DIR" -maxdepth 1 -name '*.tgz' -print | LC_ALL=C sort > "$before"
case "${PACKAGE_MANAGER:-npm}" in
npm)
npm pack "./$package_dir" --pack-destination "$DIST_DIR"
;;
pnpm)
corepack enable
( cd "$package_dir" && pnpm pack --pack-destination "$DIST_DIR" )
;;
*)
echo "::error title=Invalid package manager::PACKAGE_MANAGER must be npm or pnpm."
exit 1
;;
esac
find "$DIST_DIR" -maxdepth 1 -name '*.tgz' -print | LC_ALL=C sort > "$after"
comm -13 "$before" "$after" > "$added"
if [[ "$(wc -l < "$added" | tr -d ' ')" -ne 1 ]]; then
echo "::error title=Invalid package artifact::Packing '$package_name' must produce exactly one new tarball."
exit 1
fi
tarball="$(<"$added")"
inspect_declared_files "$package_dir" "$tarball"
tarball_package="$(tar -xzOf "$tarball" package/package.json | jq -er '.name | select(type == "string" and length > 0)')"
tarball_version="$(tar -xzOf "$tarball" package/package.json | jq -er '.version | select(type == "string" and length > 0)')"
if [[ "$tarball_package" != "$package_name" ]]; then
echo "::error title=Invalid package artifact::$(basename "$tarball") identifies '$tarball_package', not declared package '$package_name'."
exit 1
fi
tarball_release_tag="$(release_tag_for "$tarball_package" "$tarball_version")"
jq -cn \
--arg file "$(basename "$tarball")" \
--arg package "$package_name" \
--arg release_tag "$tarball_release_tag" \
--arg sha256 "$(sha256sum "$tarball" | awk '{print $1}')" \
--arg version "$tarball_version" \
'{file: $file, package: $package, release_tag: $release_tag, sha256: $sha256, version: $version}' >> "$RECORDS_FILE"
}

case "${PACKAGE_MANAGER:-npm}" in
npm)
npm run build
;;
pnpm)
corepack enable
pnpm run build
;;
*)
echo "::error title=Invalid package manager::PACKAGE_MANAGER must be npm or pnpm."
exit 1
;;
esac

case "$PROJECT_TYPE" in
single)
package_name="$(jq -er '.name | select(type == "string" and length > 0)' package.json)"
pack_package "." "$package_name"
;;
workspaces)
jq -e '
.release.packages
| type == "array" and length > 0 and
all(.[]; type == "string" and length > 0)
' "$GITHUB_WORKSPACE/.github/inditextech-ci-node.json" > /dev/null
while IFS= read -r package_name; do
member="$(printf '%s' "${package_name##*/}" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//')"
package_dir="packages/$member"
if [[ ! -f "$package_dir/package.json" ]] || [[ "$(jq -r '.name' "$package_dir/package.json")" != "$package_name" ]]; then
echo "::error title=Unknown workspace package::release.packages entry '$package_name' does not resolve to its declared workspace manifest."
exit 1
fi
pack_package "$package_dir" "$package_name"
done < <(jq -r '.release.packages[]' "$GITHUB_WORKSPACE/.github/inditextech-ci-node.json")
;;
*)
echo "::error title=Invalid project type::PROJECT_TYPE must be single or workspaces."
exit 1
;;
esac

jq -cs . "$RECORDS_FILE" > "$HANDOFF_DIR/tarballs.json"
echo "handoff_dir=$HANDOFF_DIR" >> "$GITHUB_OUTPUT"

- name: Create delegated release handoff
id: delegated-handoff
if: vars.RELEASE_LIFECYCLE == 'delegated'
env:
echo "::error title=Invalid package manager::PACKAGE_MANAGER must be npm or pnpm."
exit 1
;;
npm) npm ci ;;
Governance-Provenance: hmac-sha256:9f99e6a9dcda0869e8a2b16e662ab3934595ca748bc2a31590f6fe405a176c10
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-release Do not publish a release for this change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant