Skip to content

Commit 7879f40

Browse files
committed
actions: make lockfile-extension generation atomic
Stage the generated model pack in a temp dir inside the WIP database and publish it with a single rename only after it is fully written, with an EXIT trap that cleans up on any failure. Previously a failed 'go build' (expected until the private actions-lockfile dependency is public) left a half-written pack dir behind (an ext/ with no qlpack.yml) that could break analyses run with --additional-packs. Verified across three cases: repo with a lockfile (atomic publish), repo without one (clean no-op), and no Go toolchain available (graceful skip, no partial pack).
1 parent b1165b5 commit 7879f40

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

actions/extractor/tools/generate-lockfile-extension.sh

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,15 @@ SCRIPT_DIR="$(CDPATH= cd "$(dirname "$0")" && pwd)"
4242
GEN_DIR="${SCRIPT_DIR}/lockfile-extension-generator"
4343

4444
PACK_DIR="${CODEQL_EXTRACTOR_ACTIONS_WIP_DATABASE}/lockfile-extension"
45-
EXT_DIR="${PACK_DIR}/ext"
46-
mkdir -p "${EXT_DIR}"
45+
46+
# Stage the pack in a sibling temp dir inside the database directory (same
47+
# filesystem as the final location) so the final `mv` is an atomic rename, and
48+
# only publish a complete pack on success -- a failure part-way through never
49+
# leaves a half-written pack dir (e.g. an `ext/` with no `qlpack.yml`) that would
50+
# break `--additional-packs`.
51+
STAGE_DIR="$(mktemp -d "${CODEQL_EXTRACTOR_ACTIONS_WIP_DATABASE}/lockfile-extension.XXXXXX")"
52+
trap 'rm -rf "${STAGE_DIR}"' EXIT
53+
mkdir -p "${STAGE_DIR}/ext"
4754

4855
# Resolve the generator: prefer a prebuilt binary shipped with the extractor;
4956
# otherwise build from source with the Go toolchain if it is available.
@@ -52,7 +59,7 @@ RUN_GENERATOR=""
5259
if [ -x "${GEN_BIN}" ]; then
5360
RUN_GENERATOR="${GEN_BIN}"
5461
elif command -v go >/dev/null 2>&1; then
55-
BUILT_BIN="${CODEQL_EXTRACTOR_ACTIONS_SCRATCH_DIR:-${PACK_DIR}}/lockfile-extension-generator"
62+
BUILT_BIN="${STAGE_DIR}/lockfile-extension-generator"
5663
echo "Building lockfile-extension-generator from source with 'go build'."
5764
( cd "${GEN_DIR}" && go build -o "${BUILT_BIN}" . )
5865
RUN_GENERATOR="${BUILT_BIN}"
@@ -61,9 +68,9 @@ else
6168
exit 0
6269
fi
6370

64-
"${RUN_GENERATOR}" "${SRC_ROOT}" "${EXT_DIR}/pinned_by_lockfile.model.yml"
71+
"${RUN_GENERATOR}" "${SRC_ROOT}" "${STAGE_DIR}/ext/pinned_by_lockfile.model.yml"
6572

66-
cat > "${PACK_DIR}/qlpack.yml" <<'EOF'
73+
cat > "${STAGE_DIR}/qlpack.yml" <<'EOF'
6774
name: codeql/actions-lockfile-pins
6875
version: 0.0.1
6976
library: true
@@ -77,4 +84,10 @@ dataExtensions:
7784
- ext/*.model.yml
7885
EOF
7986

87+
# Publish atomically: the pack only appears in the database once fully written.
88+
rm -f "${STAGE_DIR}/lockfile-extension-generator"
89+
rm -rf "${PACK_DIR}"
90+
mv "${STAGE_DIR}" "${PACK_DIR}"
91+
trap - EXIT
92+
8093
echo "Wrote lockfile-pinned data extension to '${PACK_DIR}'."

0 commit comments

Comments
 (0)