Update release_pipeline.yml
This commit is contained in:
224
.github/workflows/release_pipeline.yml
vendored
224
.github/workflows/release_pipeline.yml
vendored
@@ -64,6 +64,8 @@ concurrency: group: release-pipeline-${{ github.ref_name }} cancel-in-progress:
|
|||||||
|
|
||||||
defaults: run: shell: bash
|
defaults: run: shell: bash
|
||||||
|
|
||||||
|
Principle of least privilege. Jobs elevate as needed.
|
||||||
|
|
||||||
permissions: contents: read
|
permissions: contents: read
|
||||||
|
|
||||||
jobs: guard: name: 00 Guardrails and metadata runs-on: ubuntu-latest
|
jobs: guard: name: 00 Guardrails and metadata runs-on: ubuntu-latest
|
||||||
@@ -81,8 +83,6 @@ outputs:
|
|||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
|
||||||
pull-requests: read
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (best effort)
|
- name: Checkout (best effort)
|
||||||
@@ -99,20 +99,15 @@ steps:
|
|||||||
const repo = context.repo.repo;
|
const repo = context.repo.repo;
|
||||||
const username = context.actor;
|
const username = context.actor;
|
||||||
|
|
||||||
const res = await github.rest.repos.getCollaboratorPermissionLevel({
|
const res = await github.rest.repos.getCollaboratorPermissionLevel({ owner, repo, username });
|
||||||
owner,
|
const perm = (res && res.data && res.data.permission) ? String(res.data.permission).toLowerCase() : "unknown";
|
||||||
repo,
|
const allowed = (perm === "admin" || perm === "maintain");
|
||||||
username,
|
|
||||||
});
|
|
||||||
|
|
||||||
const perm = (res?.data?.permission || '').toLowerCase();
|
core.setOutput("permission", perm);
|
||||||
const allowed = (perm === 'admin' || perm === 'maintain');
|
core.setOutput("allowed", allowed ? "true" : "false");
|
||||||
|
|
||||||
core.setOutput('permission', perm || 'unknown');
|
|
||||||
core.setOutput('allowed', allowed ? 'true' : 'false');
|
|
||||||
|
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
core.setFailed(`Actor ${username} lacks required role (admin or maintain). Detected permission: ${perm || 'unknown'}.`);
|
core.setFailed(`Actor ${username} lacks required role (admin or maintain). Detected permission: ${perm}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
- name: Validate trigger and extract metadata
|
- name: Validate trigger and extract metadata
|
||||||
@@ -252,9 +247,9 @@ steps:
|
|||||||
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 '}
|
printf '}\n'
|
||||||
|
echo "```"
|
||||||
' echo "```" } >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
{
|
{
|
||||||
echo "### Git snapshot"
|
echo "### Git snapshot"
|
||||||
@@ -333,23 +328,12 @@ steps:
|
|||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
{
|
{
|
||||||
echo "### Run context"
|
echo "### Git snapshot"
|
||||||
echo "```json"
|
echo "```"
|
||||||
printf '{'
|
git status --porcelain=v1 || true
|
||||||
printf '"repository":"%s",' "${GITHUB_REPOSITORY}"
|
git log -1 --pretty=fuller || true
|
||||||
printf '"workflow":"%s",' "${GITHUB_WORKFLOW}"
|
echo "```"
|
||||||
printf '"job":"%s",' "${GITHUB_JOB}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
printf '"run_id":%s,' "${GITHUB_RUN_ID}"
|
|
||||||
printf '"run_number":%s,' "${GITHUB_RUN_NUMBER}"
|
|
||||||
printf '"run_attempt":%s,' "${GITHUB_RUN_ATTEMPT}"
|
|
||||||
printf '"run_url":"%s",' "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
|
|
||||||
printf '"actor":"%s",' "${GITHUB_ACTOR}"
|
|
||||||
printf '"event":"%s",' "${GITHUB_EVENT_NAME}"
|
|
||||||
printf '"ref_name":"%s",' "${GITHUB_REF_NAME}"
|
|
||||||
printf '"sha":"%s"' "${GITHUB_SHA}"
|
|
||||||
printf '}
|
|
||||||
|
|
||||||
' echo "```" } >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
|
|
||||||
normalize_dates: name: 02 Normalize dates on promoted branch runs-on: ubuntu-latest needs: - guard - promote_branch
|
normalize_dates: name: 02 Normalize dates on promoted branch runs-on: ubuntu-latest needs: - guard - promote_branch
|
||||||
|
|
||||||
@@ -418,9 +402,13 @@ steps:
|
|||||||
{
|
{
|
||||||
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
|
printf '%s\n' "${CANDIDATES[@]}"
|
||||||
|
echo "Discovered candidates (first 5):"
|
||||||
' "${CANDIDATES[@]}" echo "Discovered candidates (first 5):" echo "${FOUND:-<none>}" echo "Required action: add scripts/release/update_dates.sh (preferred) to the repo." } >> "${GITHUB_STEP_SUMMARY}" exit 1 fi
|
echo "${FOUND:-<none>}"
|
||||||
|
echo "Required action: add scripts/release/update_dates.sh (preferred) to the repo."
|
||||||
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Using date script: ${SCRIPT}" >> "${GITHUB_STEP_SUMMARY}"
|
echo "Using date script: ${SCRIPT}" >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
@@ -534,12 +522,12 @@ steps:
|
|||||||
printf '%s"%s"' "${sep}" "${m}"
|
printf '%s"%s"' "${sep}" "${m}"
|
||||||
sep=",";
|
sep=",";
|
||||||
done
|
done
|
||||||
printf '],"channel":"%s","deploy_dry_run":"%s","credential_presence":{"FTP_KEY":"%s","FTP_PASSWORD":"%s"}}
|
printf '],"channel":"%s","deploy_dry_run":"%s","credential_presence":{"FTP_KEY":"%s","FTP_PASSWORD":"%s"}}\n' \
|
||||||
|
"${CHANNEL}" "${DEPLOY_DRY_RUN:-false}" \
|
||||||
'
|
"$( [ "${key_present}" = "true" ] && echo present || echo missing )" \
|
||||||
"${CHANNEL}" "${DEPLOY_DRY_RUN:-false}"
|
"$( [ "${pw_present}" = "true" ] && echo present || echo missing )"
|
||||||
"$( [ "${key_present}" = "true" ] && echo present || echo missing )"
|
echo "```"
|
||||||
"$( [ "${pw_present}" = "true" ] && echo present || echo missing )" echo "```" } >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
if [ "${#missing[@]}" -gt 0 ]; then
|
if [ "${#missing[@]}" -gt 0 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
@@ -582,9 +570,11 @@ if [ "${#missing[@]}" -gt 0 ]; then
|
|||||||
printf '%s"%s"' "${sep}" "${m}"
|
printf '%s"%s"' "${sep}" "${m}"
|
||||||
sep=",";
|
sep=",";
|
||||||
done
|
done
|
||||||
printf ']}
|
printf ']}\n'
|
||||||
|
echo "```"
|
||||||
' echo "```" } >> "${GITHUB_STEP_SUMMARY}" exit 1 fi
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
ran=()
|
ran=()
|
||||||
skipped=()
|
skipped=()
|
||||||
@@ -636,9 +626,9 @@ ran=()
|
|||||||
sep=",";
|
sep=",";
|
||||||
done
|
done
|
||||||
|
|
||||||
printf ']}
|
printf ']}\n'
|
||||||
|
echo "```"
|
||||||
' echo "```" } >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
- name: Build Joomla ZIP (extension type aware, src-only archive)
|
- name: Build Joomla ZIP (extension type aware, src-only archive)
|
||||||
id: build
|
id: build
|
||||||
@@ -691,7 +681,6 @@ ran=()
|
|||||||
|
|
||||||
echo "zip_name=${ZIP}" >> "${GITHUB_OUTPUT}"
|
echo "zip_name=${ZIP}" >> "${GITHUB_OUTPUT}"
|
||||||
echo "dist_dir=${DIST_DIR}" >> "${GITHUB_OUTPUT}"
|
echo "dist_dir=${DIST_DIR}" >> "${GITHUB_OUTPUT}"
|
||||||
echo "root=src" >> "${GITHUB_OUTPUT}"
|
|
||||||
echo "manifest=${MANIFEST}" >> "${GITHUB_OUTPUT}"
|
echo "manifest=${MANIFEST}" >> "${GITHUB_OUTPUT}"
|
||||||
echo "ext_type=${EXT_TYPE}" >> "${GITHUB_OUTPUT}"
|
echo "ext_type=${EXT_TYPE}" >> "${GITHUB_OUTPUT}"
|
||||||
|
|
||||||
@@ -700,7 +689,7 @@ ran=()
|
|||||||
{
|
{
|
||||||
echo "### Build report"
|
echo "### Build report"
|
||||||
echo "```json"
|
echo "```json"
|
||||||
echo "{\"repository\":\"${GITHUB_REPOSITORY}\",\"workflow\":\"${GITHUB_WORKFLOW}\",\"job\":\"${GITHUB_JOB}\",\"run_id\":${GITHUB_RUN_ID},\"run_number\":${GITHUB_RUN_NUMBER},\"run_attempt\":${GITHUB_RUN_ATTEMPT},\"run_url\":\"${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}\",\"actor\":\"${GITHUB_ACTOR}\",\"sha\":\"${GITHUB_SHA}\",\"root\":\"src\",\"manifest\":\"${MANIFEST}\",\"extension_type\":\"${EXT_TYPE}\",\"zip\":\"${DIST_DIR}/${ZIP}\",\"zip_bytes\":${ZIP_BYTES},\"archive_policy\":\"src_only\"}"
|
echo "{\"repository\":\"${GITHUB_REPOSITORY}\",\"workflow\":\"${GITHUB_WORKFLOW}\",\"job\":\"${GITHUB_JOB}\",\"run_id\":${GITHUB_RUN_ID},\"run_number\":${GITHUB_RUN_NUMBER},\"run_attempt\":${GITHUB_RUN_ATTEMPT},\"run_url\":\"${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}\",\"actor\":\"${GITHUB_ACTOR}\",\"sha\":\"${GITHUB_SHA}\",\"archive_policy\":\"src_only\",\"manifest\":\"${MANIFEST}\",\"extension_type\":\"${EXT_TYPE}\",\"zip\":\"${DIST_DIR}/${ZIP}\",\"zip_bytes\":${ZIP_BYTES}}"
|
||||||
echo "```"
|
echo "```"
|
||||||
} >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
@@ -721,7 +710,7 @@ ran=()
|
|||||||
echo "```"
|
echo "```"
|
||||||
} >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
- name: Upload ZIP to SFTP (key-preferred, password-fallback, overwrite, verified, classified)
|
- name: Upload ZIP to SFTP (key-preferred, password-fallback, overwrite, verified)
|
||||||
id: sftp
|
id: sftp
|
||||||
env:
|
env:
|
||||||
FTP_HOST: ${{ secrets.FTP_HOST }}
|
FTP_HOST: ${{ secrets.FTP_HOST }}
|
||||||
@@ -764,24 +753,12 @@ ran=()
|
|||||||
REMOTE_PATH="${FTP_PATH%/}/${CHANNEL}"
|
REMOTE_PATH="${FTP_PATH%/}/${CHANNEL}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${REMOTE_PATH}" ] || [ "${REMOTE_PATH}" = "/" ]; then
|
|
||||||
echo "ERROR: Unsafe REMOTE_PATH resolved (${REMOTE_PATH:-<empty>})" >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if printf '%s' "${REMOTE_PATH}" | awk -F/ '{print NF-1}' | grep -Eq '^[01]$'; then
|
|
||||||
echo "ERROR: Remote path lacks depth guardrail: ${REMOTE_PATH}" >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
AUTH_MODE="password"
|
AUTH_MODE="password"
|
||||||
if [ -n "${FTP_KEY:-}" ]; then
|
if [ -n "${FTP_KEY:-}" ]; then
|
||||||
AUTH_MODE="key"
|
AUTH_MODE="key"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PASSWORD_PRESENT="$( [ -n "${FTP_PASSWORD:-}" ] && echo true || echo false )"
|
if [ "${AUTH_MODE}" = "password" ] && [ -z "${FTP_PASSWORD:-}" ]; then
|
||||||
KEY_PRESENT="$( [ -n "${FTP_KEY:-}" ] && echo true || echo false )"
|
|
||||||
|
|
||||||
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
|
||||||
@@ -800,21 +777,11 @@ ran=()
|
|||||||
printf '"host":"%s",' "${FTP_HOST}"
|
printf '"host":"%s",' "${FTP_HOST}"
|
||||||
printf '"port":"%s",' "${PORT:-default}"
|
printf '"port":"%s",' "${PORT:-default}"
|
||||||
printf '"remote_path":"%s",' "${REMOTE_PATH}"
|
printf '"remote_path":"%s",' "${REMOTE_PATH}"
|
||||||
printf '"overwrite_policy":"same_filename_only",'
|
printf '"overwrite":true,'
|
||||||
printf '"cleanup_policy":"disabled",'
|
printf '"dry_run":%s' "${DRY_RUN}"
|
||||||
printf '"dry_run":%s,' "${DRY_RUN}"
|
printf '}\n'
|
||||||
printf '"zip":"%s",' "${ZIP}"
|
echo "```"
|
||||||
printf '"credential_presence":{'
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
printf '"FTP_KEY":"%s",' "$( [ "${KEY_PRESENT}" = "true" ] && echo present || echo missing )"
|
|
||||||
printf '"FTP_PASSWORD":"%s"' "$( [ "${PASSWORD_PRESENT}" = "true" ] && echo present || echo missing )"
|
|
||||||
printf '}'
|
|
||||||
printf '}
|
|
||||||
|
|
||||||
' echo "```" } >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
|
|
||||||
if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|
||||||
echo "Password provided but ignored because key auth is in use." >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y lftp openssh-client putty-tools
|
sudo apt-get install -y lftp openssh-client putty-tools
|
||||||
@@ -830,11 +797,7 @@ if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|||||||
if grep -Eq '^Encryption: *none[[:space:]]*$' ~/.ssh/key.ppk; then
|
if grep -Eq '^Encryption: *none[[:space:]]*$' ~/.ssh/key.ppk; then
|
||||||
PPK_PASSPHRASE=""
|
PPK_PASSPHRASE=""
|
||||||
else
|
else
|
||||||
if [ -z "${FTP_PASSWORD:-}" ]; then
|
PPK_PASSPHRASE="${FTP_PASSWORD:-}"
|
||||||
echo "ERROR: Encrypted PPK detected but FTP_PASSWORD not provided" >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
PPK_PASSPHRASE="${FTP_PASSWORD}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${PPK_PASSPHRASE}" ]; then
|
if [ -n "${PPK_PASSPHRASE}" ]; then
|
||||||
@@ -861,46 +824,8 @@ if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|||||||
OPEN="open -u '${FTP_USER}','${FTP_PASSWORD}', sftp://${HOSTPORT}"
|
OPEN="open -u '${FTP_USER}','${FTP_PASSWORD}', sftp://${HOSTPORT}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ZIP_BYTES_LOCAL="$(stat -c%s "${DIST_DIR}/${ZIP}")"
|
|
||||||
|
|
||||||
set +e
|
|
||||||
preflight_log="$(mktemp)"
|
|
||||||
lftp -d -e "\
|
|
||||||
set sftp:auto-confirm yes; \
|
|
||||||
set cmd:trace yes; \
|
|
||||||
set net:timeout 30; \
|
|
||||||
set net:max-retries 3; \
|
|
||||||
set net:reconnect-interval-base 5; \
|
|
||||||
${CONNECT}; \
|
|
||||||
${OPEN}; \
|
|
||||||
mkdir -p '${REMOTE_PATH}'; \
|
|
||||||
cd '${REMOTE_PATH}'; \
|
|
||||||
ls -la; \
|
|
||||||
bye" >"${preflight_log}" 2>&1
|
|
||||||
preflight_rc=$?
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ "${preflight_rc}" -ne 0 ]; then
|
|
||||||
{
|
|
||||||
echo "### SFTP preflight log"
|
|
||||||
echo "```"
|
|
||||||
tail -n 400 "${preflight_log}" || true
|
|
||||||
echo "```"
|
|
||||||
} >> "${GITHUB_STEP_SUMMARY}" || true
|
|
||||||
exit "${preflight_rc}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if grep -F " ${ZIP}" "${preflight_log}" >/dev/null 2>&1; then
|
|
||||||
echo "Remote file already exists and will be overwritten (same filename policy): ${ZIP}" >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
else
|
|
||||||
echo "Remote file not present, proceeding with first publish: ${ZIP}" >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${DRY_RUN}" = "true" ]; then
|
if [ "${DRY_RUN}" = "true" ]; then
|
||||||
{
|
echo "Dry run enabled. Upload skipped." >> "${GITHUB_STEP_SUMMARY}"
|
||||||
echo "### Dry run"
|
|
||||||
echo "Dry run enabled. Upload skipped."
|
|
||||||
} >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
echo "auth_mode=${AUTH_MODE}" >> "${GITHUB_OUTPUT}"
|
echo "auth_mode=${AUTH_MODE}" >> "${GITHUB_OUTPUT}"
|
||||||
echo "remote_path=${REMOTE_PATH}" >> "${GITHUB_OUTPUT}"
|
echo "remote_path=${REMOTE_PATH}" >> "${GITHUB_OUTPUT}"
|
||||||
echo "host=${FTP_HOST}" >> "${GITHUB_OUTPUT}"
|
echo "host=${FTP_HOST}" >> "${GITHUB_OUTPUT}"
|
||||||
@@ -918,6 +843,7 @@ if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|||||||
set net:reconnect-interval-base 5; \
|
set net:reconnect-interval-base 5; \
|
||||||
${CONNECT}; \
|
${CONNECT}; \
|
||||||
${OPEN}; \
|
${OPEN}; \
|
||||||
|
mkdir -p '${REMOTE_PATH}'; \
|
||||||
cd '${REMOTE_PATH}'; \
|
cd '${REMOTE_PATH}'; \
|
||||||
put -E '${DIST_DIR}/${ZIP}'; \
|
put -E '${DIST_DIR}/${ZIP}'; \
|
||||||
ls -l; \
|
ls -l; \
|
||||||
@@ -925,55 +851,21 @@ if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|||||||
rc=$?
|
rc=$?
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
failure_class="none"
|
|
||||||
if [ "${rc}" -ne 0 ]; then
|
if [ "${rc}" -ne 0 ]; then
|
||||||
if grep -Ei 'auth|authentication|login failed' "${upload_log}" >/dev/null 2>&1; then
|
|
||||||
failure_class="auth_failure"
|
|
||||||
elif grep -Ei 'name or service not known|temporary failure in name resolution|no such host' "${upload_log}" >/dev/null 2>&1; then
|
|
||||||
failure_class="dns_failure"
|
|
||||||
elif grep -Ei 'connection timed out|timeout' "${upload_log}" >/dev/null 2>&1; then
|
|
||||||
failure_class="timeout"
|
|
||||||
elif grep -Ei 'no route to host|network is unreachable|connection refused' "${upload_log}" >/dev/null 2>&1; then
|
|
||||||
failure_class="network_failure"
|
|
||||||
elif grep -Ei 'permission denied' "${upload_log}" >/dev/null 2>&1; then
|
|
||||||
failure_class="permission_denied"
|
|
||||||
else
|
|
||||||
failure_class="unknown"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
{
|
{
|
||||||
echo "### SFTP session log"
|
echo "### SFTP session log"
|
||||||
echo "```"
|
echo "```"
|
||||||
tail -n 400 "${upload_log}" || true
|
tail -n 400 "${upload_log}" || true
|
||||||
echo "```"
|
echo "```"
|
||||||
} >> "${GITHUB_STEP_SUMMARY}" || true
|
} >> "${GITHUB_STEP_SUMMARY}" || true
|
||||||
|
|
||||||
if [ "${rc}" -ne 0 ]; then
|
|
||||||
{
|
|
||||||
echo "### SFTP failure classification"
|
|
||||||
echo "```json"
|
|
||||||
echo "{\"status\":\"fail\",\"class\":\"${failure_class}\",\"exit_code\":${rc}}"
|
|
||||||
echo "```"
|
|
||||||
} >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
exit "${rc}"
|
exit "${rc}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -F " ${ZIP}" "${upload_log}" >/dev/null 2>&1; then
|
ZIP_BYTES_LOCAL="$(stat -c%s "${DIST_DIR}/${ZIP}")"
|
||||||
echo "ERROR: Upload completed but verification failed. ZIP not visible in remote listing." >> "${GITHUB_STEP_SUMMARY}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ZIP_BYTES_REMOTE="unknown"
|
|
||||||
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"
|
|
||||||
fi
|
|
||||||
|
|
||||||
{
|
{
|
||||||
echo "### SFTP upload report"
|
echo "### SFTP upload report"
|
||||||
echo "```json"
|
echo "```json"
|
||||||
echo "{\"status\":\"ok\",\"protocol\":\"sftp\",\"auth_mode\":\"${AUTH_MODE}\",\"host\":\"${FTP_HOST}\",\"port\":\"${PORT:-default}\",\"remote_path\":\"${REMOTE_PATH}\",\"zip\":\"${ZIP}\",\"zip_bytes_local\":${ZIP_BYTES_LOCAL},\"zip_bytes_remote\":\"${ZIP_BYTES_REMOTE}\",\"overwrite\":true,\"cleanup_policy\":\"disabled\"}"
|
echo "{\"status\":\"ok\",\"protocol\":\"sftp\",\"auth_mode\":\"${AUTH_MODE}\",\"host\":\"${FTP_HOST}\",\"port\":\"${PORT:-default}\",\"remote_path\":\"${REMOTE_PATH}\",\"zip\":\"${ZIP}\",\"zip_bytes_local\":${ZIP_BYTES_LOCAL},\"overwrite\":true}"
|
||||||
echo "```"
|
echo "```"
|
||||||
} >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
|
||||||
@@ -1007,6 +899,11 @@ if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|||||||
echo "tag=${TAG}" >> "${GITHUB_OUTPUT}"
|
echo "tag=${TAG}" >> "${GITHUB_OUTPUT}"
|
||||||
|
|
||||||
- name: Generate release notes from CHANGELOG.md
|
- name: Generate release notes from CHANGELOG.md
|
||||||
|
env:
|
||||||
|
SFTP_AUTH_MODE: ${{ steps.sftp.outputs.auth_mode }}
|
||||||
|
SFTP_REMOTE_PATH: ${{ steps.sftp.outputs.remote_path }}
|
||||||
|
SFTP_HOST: ${{ steps.sftp.outputs.host }}
|
||||||
|
SFTP_PORT: ${{ steps.sftp.outputs.port }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -1026,10 +923,10 @@ if [ "${KEY_PRESENT}" = "true" ] && [ "${PASSWORD_PRESENT}" = "true" ]; then
|
|||||||
echo "- ${ZIP_ASSET}"
|
echo "- ${ZIP_ASSET}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Deployment metadata:"
|
echo "Deployment metadata:"
|
||||||
echo "- auth_mode: ${{ steps.sftp.outputs.auth_mode || 'unknown' }}"
|
echo "- auth_mode: ${SFTP_AUTH_MODE:-unknown}"
|
||||||
echo "- remote_path: ${{ steps.sftp.outputs.remote_path || 'unknown' }}"
|
echo "- remote_path: ${SFTP_REMOTE_PATH:-unknown}"
|
||||||
echo "- host: ${{ steps.sftp.outputs.host || 'unknown' }}"
|
echo "- host: ${SFTP_HOST:-unknown}"
|
||||||
echo "- port: ${{ steps.sftp.outputs.port || 'unknown' }}"
|
echo "- port: ${SFTP_PORT:-unknown}"
|
||||||
} >> RELEASE_NOTES.md
|
} >> RELEASE_NOTES.md
|
||||||
|
|
||||||
- name: Create GitHub release and attach ZIP
|
- name: Create GitHub release and attach ZIP
|
||||||
@@ -1143,7 +1040,6 @@ steps:
|
|||||||
- name: Release event telemetry
|
- name: Release event telemetry
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
{
|
{
|
||||||
echo "### Release event telemetry"
|
echo "### Release event telemetry"
|
||||||
echo "```json"
|
echo "```json"
|
||||||
|
|||||||
Reference in New Issue
Block a user