Update guardrails.yml

This commit is contained in:
2025-12-26 23:28:09 -06:00
parent b2839c10a5
commit e5ae493aaa

View File

@@ -51,21 +51,16 @@ permissions:
contents: read contents: read
jobs: jobs:
guardrails: release_config:
name: Setting Guardrails name: Release configuration
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
steps: steps:
- name: Checkout - name: Guardrails: release secrets and vars
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate required repository secrets and variables
env: env:
PROFILE: ${{ github.event.inputs.profile || 'all' }} PROFILE: ${{ github.event.inputs.profile || 'all' }}
# Release pipeline SFTP configuration (secrets + vars)
FTP_HOST: ${{ secrets.FTP_HOST }} FTP_HOST: ${{ secrets.FTP_HOST }}
FTP_USER: ${{ secrets.FTP_USER }} FTP_USER: ${{ secrets.FTP_USER }}
FTP_KEY: ${{ secrets.FTP_KEY }} FTP_KEY: ${{ secrets.FTP_KEY }}
@@ -74,67 +69,57 @@ jobs:
FTP_PROTOCOL: ${{ secrets.FTP_PROTOCOL }} FTP_PROTOCOL: ${{ secrets.FTP_PROTOCOL }}
FTP_PORT: ${{ secrets.FTP_PORT }} FTP_PORT: ${{ secrets.FTP_PORT }}
FTP_PATH_SUFFIX: ${{ vars.FTP_PATH_SUFFIX }} FTP_PATH_SUFFIX: ${{ vars.FTP_PATH_SUFFIX }}
run: | run: |
set -euxo pipefail set -euxo pipefail
profile="${PROFILE}" profile="${PROFILE}"
if [ "${profile}" != "all" ] && [ "${profile}" != "release" ] && [ "${profile}" != "scripts" ]; then
echo "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
# Centralized checklist. if [ "${profile}" = "scripts" ]; then
required_release_secrets=( echo "Profile scripts selected. Skipping release configuration checks." >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
required=(
"FTP_HOST" "FTP_HOST"
"FTP_USER" "FTP_USER"
"FTP_KEY" "FTP_KEY"
"FTP_PATH" "FTP_PATH"
) )
optional_release=( optional=(
"FTP_PASSWORD" # Only needed for encrypted PPK conversion "FTP_PASSWORD"
"FTP_PROTOCOL" # Defaults to sftp in pipelines "FTP_PROTOCOL"
"FTP_PORT" # Defaults to provider default "FTP_PORT"
"FTP_PATH_SUFFIX" # Variable, optional "FTP_PATH_SUFFIX"
)
required_script_files=(
"scripts/validate_manifest.sh"
"scripts/validate_xml_wellformed.sh"
"scripts/validate_changelog.sh"
"scripts/validate_tabs.sh"
"scripts/validate_paths.sh"
"scripts/validate_version_alignment.sh"
"scripts/validate_language_structure.sh"
"scripts/validate_php_syntax.sh"
"scripts/validate_no_secrets.sh"
"scripts/validate_license_headers.sh"
) )
missing=() missing=()
missing_optional=() missing_optional=()
missing_files=()
check_release() { for k in "${required[@]}"; do
for k in "${required_release_secrets[@]}"; do
v="${!k:-}" v="${!k:-}"
if [ -z "${v}" ]; then if [ -z "${v}" ]; then
missing+=("${k}") missing+=("${k}")
fi fi
done done
# Optional configuration. for k in "${optional[@]}"; do
for k in "${optional_release[@]}"; do
v="${!k:-}" v="${!k:-}"
if [ -z "${v}" ]; then if [ -z "${v}" ]; then
missing_optional+=("${k}") missing_optional+=("${k}")
fi fi
done done
# Protocol sanity if provided.
proto="${FTP_PROTOCOL:-sftp}" proto="${FTP_PROTOCOL:-sftp}"
if [ -n "${FTP_PROTOCOL:-}" ] && [ "${proto}" != "sftp" ]; then if [ -n "${FTP_PROTOCOL:-}" ] && [ "${proto}" != "sftp" ]; then
missing+=("FTP_PROTOCOL_INVALID") missing+=("FTP_PROTOCOL_INVALID")
fi fi
# Key format guardrail (do not print key). # Key format guardrail (do not print key material).
if [ -n "${FTP_KEY:-}" ]; then if [ -n "${FTP_KEY:-}" ]; then
first_line="$(printf '%s' "${FTP_KEY}" | head -n 1 || true)" first_line="$(printf '%s' "${FTP_KEY}" | head -n 1 || true)"
if printf '%s' "${first_line}" | grep -q '^PuTTY-User-Key-File-'; then if printf '%s' "${first_line}" | grep -q '^PuTTY-User-Key-File-'; then
@@ -149,122 +134,159 @@ jobs:
key_format="missing" key_format="missing"
fi fi
echo "KEY_FORMAT=${key_format}" >> "${GITHUB_STEP_SUMMARY}"
}
check_scripts() {
for f in "${required_script_files[@]}"; do
if [ ! -f "${f}" ]; then
missing_files+=("${f}")
fi
done
# Tooling expectations: scripts may rely on php and xmllint.
# Do not fail on tooling here; CI runners can install dependencies.
# Still report as guardrail visibility.
tool_missing=()
command -v php >/dev/null 2>&1 || tool_missing+=("php")
command -v xmllint >/dev/null 2>&1 || tool_missing+=("xmllint")
if [ "${#tool_missing[@]}" -gt 0 ]; then
echo "WARN: Missing tools on runner (install in workflow when required): ${tool_missing[*]}" >> "${GITHUB_STEP_SUMMARY}"
fi
}
case "${profile}" in
release)
check_release
;;
scripts)
check_scripts
;;
all)
check_release
check_scripts
;;
*)
echo "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
;;
esac
# Emit report.
{ {
echo "### Guardrails: release configuration"
echo "KEY_FORMAT=${key_format}"
echo ""
echo "### Guardrails report (JSON)" echo "### Guardrails report (JSON)"
echo "```json" echo "```json"
printf '{"repository":"%s","profile":"%s","checked":{' "${GITHUB_REPOSITORY}" "${profile}" printf '{"profile":"%s","checked":{"required":[' "${profile}"
printf '"release_required":['
sep="" sep=""
for c in "${required_release_secrets[@]}"; do for c in "${required[@]}"; do
printf '%s"%s"' "${sep}" "${c}" printf '%s"%s"' "${sep}" "${c}"
sep=","; sep=",";
done done
printf '],"optional":['
printf '],"release_optional":['
sep="" sep=""
for c in "${optional_release[@]}"; do for c in "${optional[@]}"; do
printf '%s"%s"' "${sep}" "${c}" printf '%s"%s"' "${sep}" "${c}"
sep=","; sep=",";
done done
printf ']},"missing_required":['
printf '],"script_files":['
sep=""
for c in "${required_script_files[@]}"; do
printf '%s"%s"' "${sep}" "${c}"
sep=",";
done
printf ']},'
printf '"missing_required":['
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 '],"missing_optional":[' printf '],"missing_optional":['
sep="" sep=""
for m in "${missing_optional[@]}"; do for m in "${missing_optional[@]}"; do
printf '%s"%s"' "${sep}" "${m}" printf '%s"%s"' "${sep}" "${m}"
sep=","; sep=",";
done done
printf ']}
'
echo "```"
} >> "${GITHUB_STEP_SUMMARY}"
printf '],"missing_script_files":[' if [ "${#missing[@]}" -gt 0 ]; then
echo "### Missing required release configuration" >> "${GITHUB_STEP_SUMMARY}"
for m in "${missing[@]}"; do
echo "- ${m}" >> "${GITHUB_STEP_SUMMARY}"
done
fi
if [ "${#missing_optional[@]}" -gt 0 ]; then
echo "### Missing optional release configuration" >> "${GITHUB_STEP_SUMMARY}"
for m in "${missing_optional[@]}"; do
echo "- ${m}" >> "${GITHUB_STEP_SUMMARY}"
done
fi
if [ "${#missing[@]}" -gt 0 ]; then
echo "MISSING_REQUIRED: ${missing[*]}" >&2
echo "ERROR: Guardrails failed. Missing required release configuration." >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
scripts_config:
name: Scripts and tooling
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Guardrails: script files and toolchain
env:
PROFILE: ${{ github.event.inputs.profile || 'all' }}
run: |
set -euxo pipefail
profile="${PROFILE}"
if [ "${profile}" != "all" ] && [ "${profile}" != "release" ] && [ "${profile}" != "scripts" ]; then
echo "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
if [ "${profile}" = "release" ]; then
echo "Profile release selected. Skipping scripts checks." >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
required_script_files=(
"scripts/validate/manifest.sh"
"scripts/validate/xml_wellformed.sh"
"scripts/validate/changelog.sh"
"scripts/validate/tabs.sh"
"scripts/validate/paths.sh"
"scripts/validate/version_alignment.sh"
"scripts/validate/language_structure.sh"
"scripts/validate/php_syntax.sh"
"scripts/validate/no_secrets.sh"
"scripts/validate/license_headers.sh"
)
legacy_script_files=(
"scripts/validate_manifest.sh"
"scripts/validate_xml_wellformed.sh"
"scripts/validate_changelog.sh"
"scripts/validate_tabs.sh"
"scripts/validate_paths.sh"
"scripts/validate_version_alignment.sh"
"scripts/validate_language_structure.sh"
"scripts/validate_php_syntax.sh"
"scripts/validate_no_secrets.sh"
"scripts/validate_license_headers.sh"
)
fi
done
# Report legacy scripts if present so teams can clean up.
for f in "${legacy_script_files[@]}"; do
if [ -f "${f}" ]; then
legacy_present+=("${f}")
fi
done
tools_to_install=()
command -v php >/dev/null 2>&1 || tools_to_install+=("php-cli")
command -v xmllint >/dev/null 2>&1 || tools_to_install+=("libxml2-utils")
if [ "${#tools_to_install[@]}" -gt 0 ]; then
echo "Installing missing tools: ${tools_to_install[*]}" >> "${GITHUB_STEP_SUMMARY}"
sudo apt-get update -y
ntf '%s"%s"' "${sep}" "${c}"
sep=",";
done
printf ']},"missing_script_files":['
sep="" sep=""
for m in "${missing_files[@]}"; do for m in "${missing_files[@]}"; do
printf '%s"%s"' "${sep}" "${m}" printf '%s"%s"' "${sep}" "${m}"
sep=","; sep=",";
done done
printf '],"legacy_present":['
sep=""
for m in "${legacy_present[@]}"; do
printf '%s"%s"' "${sep}" "${m}"
sep=",";
done
printf ']}' printf ']}'
echo echo
echo "```" echo "```"
} >> "${GITHUB_STEP_SUMMARY}" } >> "${GITHUB_STEP_SUMMARY}"
# Human-readable missing items (in addition to JSON)
if [ "${#missing[@]}" -gt 0 ]; then
echo "### Missing required configuration" >> "${GITHUB_STEP_SUMMARY}"
for m in "${missing[@]}"; do
echo "- ${m}" >> "${GITHUB_STEP_SUMMARY}"
done
fi
if [ "${#missing_optional[@]}" -gt 0 ]; then
echo "### Missing optional configuration" >> "${GITHUB_STEP_SUMMARY}"
for m in "${missing_optional[@]}"; do
echo "- ${m}" >> "${GITHUB_STEP_SUMMARY}"
done
fi
if [ "${#missing_files[@]}" -gt 0 ]; then if [ "${#missing_files[@]}" -gt 0 ]; then
echo "### Missing script files" >> "${GITHUB_STEP_SUMMARY}" echo "### Missing script files" >> "${GITHUB_STEP_SUMMARY}"
for m in "${missing_files[@]}"; do for m in "${missing_files[@]}"; do
echo "- ${m}" >> "${GITHUB_STEP_SUMMARY}" echo "- ${m}" >> "${GITHUB_STEP_SUMMARY}"
done done
fi echo "MISSING_SCRIPT_FILES: ${missing_files[*]}" >&2
echo "ERROR: Guardrails failed. Missing required script files." >> "${GITHUB_STEP_SUMMARY}"
# Fail the workflow if required items are missing.
if [ "${#missing[@]}" -gt 0 ] || [ "${#missing_files[@]}" -gt 0 ]; then
echo "ERROR: Guardrails failed. Missing required configuration or script files." >> "${GITHUB_STEP_SUMMARY}"
exit 1 exit 1
fi fi