WIP: Update CI workflow with defensive lint for invalid bash variable assignments #12

Closed
Copilot wants to merge 3 commits from copilot/update-ci-workflow-defensiveness into main

View File

@@ -22,8 +22,8 @@
# INGROUP: MokoStandards.CI
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /.github/workflows/ci.yml
# VERSION: 01.00.00
# BRIEF: Continuous integration workflow enforcing repository standards.
# VERSION: 01.00.01
# BRIEF: Continuous integration workflow enforcing repository standards. Defensive improvements.
# NOTE:
name: Continuous Integration
@@ -45,6 +45,10 @@ on:
permissions:
contents: read
defaults:
run:
shell: bash
jobs:
ci:
name: Repository Validation Pipeline
@@ -66,27 +70,82 @@ jobs:
- name: Verify script executability
run: |
chmod +x scripts/**/*.sh || true
# Make all shell scripts executable (best-effort)
set -euo pipefail
find . -type f -name '*.sh' -print0 | xargs -0 chmod +x || true
- name: Lint for invalid bash variable assignments (detect LHS with '/')
# This step is defensive: it looks for assignments where the LHS contains a slash,
# which would result in "No such file or directory" when executed in bash.
run: |
set -euo pipefail
echo "Scanning for suspicious variable assignments (slash in LHS)..."
# Find lines that look like an assignment and contain a slash before '=' (ignore comments)
# Limit search to relevant directories to reduce false positives.
matches="$(grep -R --line-number --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=vendor -E '^[[:space:]]*[^#[:space:]][^=]*\/[^=]*=' . || true)"
if [ -n "${matches:-}" ]; then
echo "ERROR: Suspicious assignments detected (slash in LHS). Review and fix these lines:"
echo "${matches}"
echo ""
echo 'Example of a problematic line: PREfix/TOP="${BRANCH_PREFIX%%/*}"'
exit 1
fi
echo "No suspicious variable assignments found."
- name: Required validations
run: |
set -e
set -euo pipefail
scripts/validate/manifest.sh
scripts/validate/xml_wellformed.sh
# Ensure required validation scripts exist, then run them.
required_scripts=(
"scripts/validate/manifest.sh"
"scripts/validate/xml_wellformed.sh"
)
missing=()
for s in "${required_scripts[@]}"; do
if [ ! -f "${s}" ]; then
missing+=("${s}")
fi
done
if [ "${#missing[@]}" -gt 0 ]; then
echo "Required validation scripts missing:"
for m in "${missing[@]}"; do
echo " - ${m}"
done
exit 1
fi
for s in "${required_scripts[@]}"; do
chmod +x "${s}"
"${s}"
done
- name: Optional validations
run: |
set +e
scripts/validate/changelog.sh
scripts/validate/language_structure.sh
scripts/validate/license_headers.sh
scripts/validate/no_secrets.sh
scripts/validate/paths.sh
scripts/validate/php_syntax.sh
scripts/validate/tabs.sh
scripts/validate/version_alignment.sh
optional_scripts=(
"scripts/validate/changelog.sh"
"scripts/validate/language_structure.sh"
"scripts/validate/license_headers.sh"
"scripts/validate/no_secrets.sh"
"scripts/validate/paths.sh"
"scripts/validate/php_syntax.sh"
"scripts/validate/tabs.sh"
"scripts/validate/version_alignment.sh"
)
for s in "${optional_scripts[@]}"; do
if [ -f "${s}" ]; then
chmod +x "${s}"
echo "Running optional validation: ${s}"
"${s}" || echo "Optional validation failed: ${s}"
else
echo "Skipping missing optional script: ${s}"
fi
done
- name: CI summary
if: always()