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