Update release_pipeline.yml

This commit is contained in:
Jonathan Miller
2026-01-01 08:54:38 -06:00
committed by GitHub
parent 622395faac
commit aa80746b50

View File

@@ -56,7 +56,6 @@ defaults:
run:
shell: bash
# Default permissions are minimized; jobs elevate as needed.
permissions:
contents: read
@@ -79,7 +78,6 @@ jobs:
permissions:
contents: read
actions: read
# Required for permissions check via REST API
pull-requests: read
steps:
@@ -250,7 +248,8 @@ jobs:
printf '"sha":"%s",' "${GITHUB_SHA}"
printf '"runner_os":"%s",' "${RUNNER_OS}"
printf '"runner_name":"%s"' "${RUNNER_NAME}"
printf '}\n'
printf '}
'
echo "```"
} >> "${GITHUB_STEP_SUMMARY}"
@@ -348,7 +347,8 @@ jobs:
printf '"event":"%s",' "${GITHUB_EVENT_NAME}"
printf '"ref_name":"%s",' "${GITHUB_REF_NAME}"
printf '"sha":"%s"' "${GITHUB_SHA}"
printf '}\n'
printf '}
'
echo "```"
} >> "${GITHUB_STEP_SUMMARY}"
@@ -424,7 +424,8 @@ jobs:
{
echo "ERROR: Date normalization script not found in approved locations."
echo "Approved locations:"
printf '%s\n' "${CANDIDATES[@]}"
printf '%s
' "${CANDIDATES[@]}"
echo "Discovered candidates (first 5):"
echo "${FOUND:-<none>}"
echo "Required action: add scripts/release/update_dates.sh (preferred) to the repo."
@@ -506,6 +507,7 @@ jobs:
FTP_PORT: ${{ secrets.FTP_PORT }}
FTP_PATH_SUFFIX: ${{ vars.FTP_PATH_SUFFIX }}
CHANNEL: ${{ needs.guard.outputs.channel }}
DEPLOY_DRY_RUN: ${{ vars.DEPLOY_DRY_RUN }}
run: |
set -euo pipefail
@@ -513,7 +515,6 @@ jobs:
[ -n "${FTP_HOST:-}" ] || missing+=("FTP_HOST")
[ -n "${FTP_USER:-}" ] || missing+=("FTP_USER")
[ -n "${FTP_KEY:-}" ] || missing+=("FTP_KEY")
[ -n "${FTP_PATH:-}" ] || missing+=("FTP_PATH")
proto="${FTP_PROTOCOL:-sftp}"
@@ -521,18 +522,23 @@ jobs:
missing+=("FTP_PROTOCOL_INVALID")
fi
first_line="$(printf '%s' "${FTP_KEY:-}" | head -n 1 || true)"
key_present=false
if [ -n "${FTP_KEY:-}" ]; then
if printf '%s' "${first_line}" | grep -q '^PuTTY-User-Key-File-'; then
key_format="ppk"
elif printf '%s' "${first_line}" | grep -q '^-----BEGIN '; then
key_format="openssh"
else
key_format="unknown"
missing+=("FTP_KEY_FORMAT")
fi
else
key_format="missing"
key_present=true
fi
pw_present=false
if [ -n "${FTP_PASSWORD:-}" ]; then
pw_present=true
fi
auth_mode="password"
if [ "${key_present}" = "true" ]; then
auth_mode="key"
fi
if [ "${auth_mode}" = "password" ] && [ "${pw_present}" != "true" ]; then
missing+=("FTP_PASSWORD_REQUIRED")
fi
{
@@ -542,9 +548,13 @@ jobs:
sep=""
for m in "${missing[@]}"; do
printf '%s"%s"' "${sep}" "${m}"
sep=","
sep=",";
done
printf '],"key_format":"%s","channel":"%s"}\n' "${key_format}" "${CHANNEL}"
printf '],"channel":"%s","deploy_dry_run":"%s","credential_presence":{"FTP_KEY":"%s","FTP_PASSWORD":"%s"}}
' \
"${CHANNEL}" "${DEPLOY_DRY_RUN:-false}" \
"$( [ "${key_present}" = "true" ] && echo present || echo missing )" \
"$( [ "${pw_present}" = "true" ] && echo present || echo missing )"
echo "```"
} >> "${GITHUB_STEP_SUMMARY}"
@@ -587,9 +597,10 @@ jobs:
sep=""
for m in "${missing[@]}"; do
printf '%s"%s"' "${sep}" "${m}"
sep=","
sep=",";
done
printf ']}\n'
printf ']}
'
echo "```"
} >> "${GITHUB_STEP_SUMMARY}"
exit 1
@@ -621,31 +632,32 @@ jobs:
sep=""
for s in "${required_scripts[@]}"; do
printf '%s"%s"' "${sep}" "${s}"
sep=","
sep=",";
done
printf '],"optional":['
sep=""
for s in "${optional_scripts[@]}"; do
printf '%s"%s"' "${sep}" "${s}"
sep=","
sep=",";
done
printf '],"ran":['
sep=""
for s in "${ran[@]}"; do
printf '%s"%s"' "${sep}" "${s}"
sep=","
sep=",";
done
printf '],"skipped_optional":['
sep=""
for s in "${skipped[@]}"; do
printf '%s"%s"' "${sep}" "${s}"
sep=","
sep=",";
done
printf ']}\n'
printf ']}
'
echo "```"
} >> "${GITHUB_STEP_SUMMARY}"
@@ -663,7 +675,6 @@ jobs:
DIST_DIR="${GITHUB_WORKSPACE}/dist"
mkdir -p "${DIST_DIR}"
# Detect manifest inside src for type naming only.
MANIFEST=""
if [ -f "src/templateDetails.xml" ]; then
MANIFEST="src/templateDetails.xml"
@@ -691,7 +702,6 @@ jobs:
EXT_TYPE="unknown"
fi
# Policy: archive must include ONLY the src directory tree (no repo root files).
ZIP="${REPO_NAME}-${VERSION}-${CHANNEL}-${EXT_TYPE}.zip"
zip -r -X "${DIST_DIR}/${ZIP}" src \
@@ -775,7 +785,6 @@ jobs:
REMOTE_PATH="${FTP_PATH%/}/${CHANNEL}"
fi
# Guardrails: remote path safety.
if [ -z "${REMOTE_PATH}" ] || [ "${REMOTE_PATH}" = "/" ]; then
echo "ERROR: Unsafe REMOTE_PATH resolved (${REMOTE_PATH:-<empty>})" >> "${GITHUB_STEP_SUMMARY}"
exit 1
@@ -785,18 +794,15 @@ jobs:
exit 1
fi
AUTH_MODE=""
AUTH_MODE="password"
if [ -n "${FTP_KEY:-}" ]; then
AUTH_MODE="key"
else
AUTH_MODE="password"
fi
# Credential precedence: key wins when both are present.
PASSWORD_PRESENT="$( [ -n "${FTP_PASSWORD:-}" ] && echo true || echo false )"
KEY_PRESENT="$( [ -n "${FTP_KEY:-}" ] && echo true || echo false )"
if [ "${AUTH_MODE}" = "password" ] && [ -z "${FTP_PASSWORD:-}" ]; then
if [ "${AUTH_MODE}" = "password" ] && [ "${PASSWORD_PRESENT}" != "true" ]; then
echo "ERROR: FTP_PASSWORD required when FTP_KEY is not provided" >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
@@ -879,7 +885,6 @@ jobs:
ZIP_BYTES_LOCAL="$(stat -c%s "${DIST_DIR}/${ZIP}")"
# Preflight: remote collision detection and directory validation.
set +e
preflight_log="$(mktemp)"
lftp -d -e "\
@@ -898,7 +903,12 @@ jobs:
set -e
if [ "${preflight_rc}" -ne 0 ]; then
cat "${preflight_log}" >> "${GITHUB_STEP_SUMMARY}" || true
{
echo "### SFTP preflight log"
echo "```"
tail -n 400 "${preflight_log}" || true
echo "```"
} >> "${GITHUB_STEP_SUMMARY}" || true
exit "${preflight_rc}"
fi
@@ -920,7 +930,6 @@ jobs:
exit 0
fi
# Upload + verify with failure classification.
set +e
upload_log="$(mktemp)"
lftp -d -e "\
@@ -955,7 +964,6 @@ jobs:
fi
fi
# Always attach upload log to summary (bounded by job log limits, but critical for audit).
{
echo "### SFTP session log"
echo "```"
@@ -973,14 +981,12 @@ jobs:
exit "${rc}"
fi
# Verification: ensure ZIP appears in directory listing.
if ! grep -F " ${ZIP}" "${upload_log}" >/dev/null 2>&1; then
echo "ERROR: Upload completed but verification failed. ZIP not visible in remote listing." >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
ZIP_BYTES_REMOTE="unknown"
# Best-effort size extraction from ls -l output (platform dependent).
ZIP_BYTES_REMOTE="$(awk -v z="${ZIP}" '$NF==z {print $(NF-4)}' "${upload_log}" | tail -n 1 || true)"
if [ -z "${ZIP_BYTES_REMOTE}" ]; then
ZIP_BYTES_REMOTE="unknown"