From 3ff684be19c5cb153bf182dab67c26be5c2ce2d7 Mon Sep 17 00:00:00 2001 From: jkim323 Date: Mon, 15 Jun 2026 20:55:09 -0700 Subject: [PATCH 1/5] fix warning for env var and remove continue on error --- .github/workflows/frontmatter-validation.yml | 5 ++++- .github/workflows/link-lang-check.yml | 5 ++++- .github/workflows/markdown-lint.yml | 12 ++++++++++-- .github/workflows/spell-check.yml | 9 +++++---- .github/workflows/table-format.yml | 4 +++- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/.github/workflows/frontmatter-validation.yml b/.github/workflows/frontmatter-validation.yml index 3501aff06..4ab36a18b 100644 --- a/.github/workflows/frontmatter-validation.yml +++ b/.github/workflows/frontmatter-validation.yml @@ -77,7 +77,10 @@ jobs: } & scripts/linting/Validate-MarkdownFrontmatter.ps1 @params - continue-on-error: true + if ($LASTEXITCODE -ne 0) { + "FRONTMATTER_VALIDATION_FAILED=true" >> $env:GITHUB_ENV + } + exit 0 - name: Upload frontmatter validation results if: always() diff --git a/.github/workflows/link-lang-check.yml b/.github/workflows/link-lang-check.yml index b1e851ec2..a105328db 100644 --- a/.github/workflows/link-lang-check.yml +++ b/.github/workflows/link-lang-check.yml @@ -33,7 +33,10 @@ jobs: shell: pwsh run: | & scripts/linting/Invoke-LinkLanguageCheck.ps1 -ExcludePaths 'scripts/tests/**' - continue-on-error: true + if ($LASTEXITCODE -ne 0) { + "LINK_LANG_FAILED=true" >> $env:GITHUB_ENV + } + exit 0 - name: Upload results if: always() diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml index 11acda5b0..52dae4976 100644 --- a/.github/workflows/markdown-lint.yml +++ b/.github/workflows/markdown-lint.yml @@ -19,6 +19,8 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + env: + MARKDOWN_LINT_FAILED: 'false' steps: - name: Checkout code uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -40,9 +42,15 @@ jobs: - name: Run markdown lint id: markdown-lint run: | - npm run lint:md > markdown-lint-output.txt 2>&1 || echo "MARKDOWN_LINT_FAILED=true" >> "$GITHUB_ENV" + set +e + npm run lint:md > markdown-lint-output.txt 2>&1 + EXIT_CODE=$? + set -e + if [ "$EXIT_CODE" -ne 0 ]; then + echo "MARKDOWN_LINT_FAILED=true" >> "$GITHUB_ENV" + fi cat markdown-lint-output.txt - continue-on-error: true + exit 0 - name: Create annotations if: env.MARKDOWN_LINT_FAILED == 'true' diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 46edad8b7..5bbcc6732 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -19,6 +19,8 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + env: + SPELL_CHECK_FAILED: 'false' steps: - name: Checkout code uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -40,16 +42,15 @@ jobs: - name: Run spell check id: spell-check run: | - set +e # Disable errexit to capture exit code + set +e npm run spell-check > logs/spell-check-results.txt 2>&1 EXIT_CODE=$? - set -e # Re-enable errexit + set -e if [ "$EXIT_CODE" -ne 0 ]; then echo "SPELL_CHECK_FAILED=true" >> "$GITHUB_ENV" fi cat logs/spell-check-results.txt - exit "$EXIT_CODE" - continue-on-error: true + exit 0 - name: Create annotations if: env.SPELL_CHECK_FAILED == 'true' diff --git a/.github/workflows/table-format.yml b/.github/workflows/table-format.yml index 4f0a803cf..6842e273c 100644 --- a/.github/workflows/table-format.yml +++ b/.github/workflows/table-format.yml @@ -19,6 +19,8 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + env: + TABLE_FORMAT_FAILED: 'false' steps: - name: Checkout code uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -49,7 +51,7 @@ jobs: git diff --name-only fi fi - continue-on-error: true + exit 0 - name: Create annotations if: env.TABLE_FORMAT_FAILED == 'true' From a76e48e9b5a8e81cc06c9c0a90f814b0c562e7d5 Mon Sep 17 00:00:00 2001 From: jkim323 Date: Mon, 15 Jun 2026 20:59:55 -0700 Subject: [PATCH 2/5] add validatioon gate --- .github/workflows/pr-validation.yml | 103 ++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 2e830768c..5ef16f62a 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -338,3 +338,106 @@ jobs: security-events: write # Required for SARIF upload to Security tab actions: read + validation-gate: + name: Validation Gate + if: always() + needs: + - spell-check + - markdown-lint + - table-format + - psscriptanalyzer + - discover-python-projects + - python-lint + - copyright-headers + - yaml-lint + - pester-tests + - pytest + - fuzz-tests + - pip-audit + - docusaurus-tests + - frontmatter-validation + - adr-consistency-validation + - ai-artifact-validation + - msdate-freshness + - plugin-validation + - skill-validation + - link-lang-check + - markdown-link-check + - dependency-pinning-check + - workflow-permissions-check + - action-version-consistency-scan + - gitleaks-scan + - npm-audit + - codeql + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Check job results + shell: bash + run: | + echo "## Validation Gate Summary" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + + FAILED="" + + check_result() { + local name="$1" + local result="$2" + + if [ "$result" = "success" ]; then + echo "✅ **$name**: passed" >> "$GITHUB_STEP_SUMMARY" + elif [ "$result" = "skipped" ]; then + echo "⏭️ **$name**: skipped" >> "$GITHUB_STEP_SUMMARY" + elif [ "$result" = "failure" ]; then + echo "❌ **$name**: failed" >> "$GITHUB_STEP_SUMMARY" + FAILED="${FAILED}${name}, " + elif [ "$result" = "cancelled" ]; then + echo "⚠️ **$name**: cancelled" >> "$GITHUB_STEP_SUMMARY" + FAILED="${FAILED}${name} (cancelled), " + else + echo "⚠️ **$name**: ${result}" >> "$GITHUB_STEP_SUMMARY" + FAILED="${FAILED}${name} (${result}), " + fi + } + + check_result "Spell Check" "${{ needs.spell-check.result }}" + check_result "Markdown Lint" "${{ needs.markdown-lint.result }}" + check_result "Table Format" "${{ needs.table-format.result }}" + check_result "PowerShell Lint" "${{ needs.psscriptanalyzer.result }}" + check_result "Discover Python Projects" "${{ needs.discover-python-projects.result }}" + check_result "Python Lint" "${{ needs.python-lint.result }}" + check_result "Copyright Headers" "${{ needs.copyright-headers.result }}" + check_result "YAML Lint" "${{ needs.yaml-lint.result }}" + check_result "PowerShell Tests" "${{ needs.pester-tests.result }}" + check_result "Python Tests" "${{ needs.pytest.result }}" + check_result "Fuzz Tests" "${{ needs.fuzz-tests.result }}" + check_result "pip-audit" "${{ needs.pip-audit.result }}" + check_result "Docusaurus Tests" "${{ needs.docusaurus-tests.result }}" + check_result "Frontmatter Validation" "${{ needs.frontmatter-validation.result }}" + check_result "ADR Consistency" "${{ needs.adr-consistency-validation.result }}" + check_result "AI Artifact Validation" "${{ needs.ai-artifact-validation.result }}" + check_result "ms.date Freshness" "${{ needs.msdate-freshness.result }}" + check_result "Plugin Validation" "${{ needs.plugin-validation.result }}" + check_result "Skill Validation" "${{ needs.skill-validation.result }}" + check_result "Link Language Check" "${{ needs.link-lang-check.result }}" + check_result "Markdown Link Check" "${{ needs.markdown-link-check.result }}" + check_result "Dependency Pinning" "${{ needs.dependency-pinning-check.result }}" + check_result "Workflow Permissions" "${{ needs.workflow-permissions-check.result }}" + check_result "Action Version Consistency" "${{ needs.action-version-consistency-scan.result }}" + check_result "Gitleaks" "${{ needs.gitleaks-scan.result }}" + check_result "npm Audit" "${{ needs.npm-audit.result }}" + check_result "CodeQL" "${{ needs.codeql.result }}" + + if [ -n "$FAILED" ]; then + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "---" >> "$GITHUB_STEP_SUMMARY" + echo "❌ **Validation failed**: ${FAILED%, }" >> "$GITHUB_STEP_SUMMARY" + echo "One or more required checks failed: ${FAILED%, }" + exit 1 + fi + + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "---" >> "$GITHUB_STEP_SUMMARY" + echo "✅ **All validations passed**" >> "$GITHUB_STEP_SUMMARY" + From b0ecc1686188fb24753b778ef66259a5fff21d86 Mon Sep 17 00:00:00 2001 From: jkim323 Date: Mon, 15 Jun 2026 21:14:05 -0700 Subject: [PATCH 3/5] fix SC2129. --- .github/workflows/pr-validation.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 4d15b9fdd..84b23c912 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -379,8 +379,10 @@ jobs: - name: Check job results shell: bash run: | - echo "## Validation Gate Summary" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" + { + echo "## Validation Gate Summary" + echo "" + } >> "$GITHUB_STEP_SUMMARY" FAILED="" @@ -433,14 +435,18 @@ jobs: check_result "CodeQL" "${{ needs.codeql.result }}" if [ -n "$FAILED" ]; then - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "---" >> "$GITHUB_STEP_SUMMARY" - echo "❌ **Validation failed**: ${FAILED%, }" >> "$GITHUB_STEP_SUMMARY" + { + echo "" + echo "---" + echo "❌ **Validation failed**: ${FAILED%, }" + } >> "$GITHUB_STEP_SUMMARY" echo "One or more required checks failed: ${FAILED%, }" exit 1 fi - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "---" >> "$GITHUB_STEP_SUMMARY" - echo "✅ **All validations passed**" >> "$GITHUB_STEP_SUMMARY" + { + echo "" + echo "---" + echo "✅ **All validations passed**" + } >> "$GITHUB_STEP_SUMMARY" From cce5ff225b71cebbb89c581c1a13d473c3503602 Mon Sep 17 00:00:00 2001 From: jkim323 Date: Tue, 16 Jun 2026 08:52:56 -0700 Subject: [PATCH 4/5] =?UTF-8?q?add=20soft-fail=E2=80=93aware=20summary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/markdown-link-check.yml | 14 ++++++++++++-- .github/workflows/markdown-lint.yml | 9 ++++++++- .github/workflows/pr-validation.yml | 10 ++++++++-- .github/workflows/spell-check.yml | 9 ++++++++- .github/workflows/table-format.yml | 11 ++++++++++- 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/.github/workflows/markdown-link-check.yml b/.github/workflows/markdown-link-check.yml index 97102594a..54aac295e 100644 --- a/.github/workflows/markdown-link-check.yml +++ b/.github/workflows/markdown-link-check.yml @@ -8,6 +8,10 @@ on: required: false type: boolean default: false + outputs: + has-warnings: + description: 'Whether broken links were detected (true when issues exist regardless of soft-fail)' + value: ${{ jobs.markdown-link-check.outputs.has-warnings }} permissions: contents: read @@ -18,6 +22,8 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + outputs: + has-warnings: ${{ steps.link-check.outputs.has-warnings }} steps: - name: Checkout code uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -43,7 +49,11 @@ jobs: shell: pwsh run: | & scripts/linting/Markdown-Link-Check.ps1 - continue-on-error: ${{ inputs.soft-fail }} + if ($LASTEXITCODE -ne 0) { + "LINK_CHECK_FAILED=true" >> $env:GITHUB_ENV + "has-warnings=true" >> $env:GITHUB_OUTPUT + } + exit 0 - name: Upload markdown link check results if: always() @@ -54,7 +64,7 @@ jobs: retention-days: 30 - name: Check results and fail if needed - if: ${{ !inputs.soft-fail && steps.link-check.outcome == 'failure' }} + if: env.LINK_CHECK_FAILED == 'true' && !inputs.soft-fail shell: pwsh run: | Write-Host "Markdown link check failed and soft-fail is false. Failing the job." diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml index 52dae4976..b00ca4c02 100644 --- a/.github/workflows/markdown-lint.yml +++ b/.github/workflows/markdown-lint.yml @@ -68,7 +68,14 @@ jobs: - name: Add job summary if: always() run: | - if [ "${{ env.MARKDOWN_LINT_FAILED }}" == "true" ]; then + if [ "${{ env.MARKDOWN_LINT_FAILED }}" == "true" ] && [ "${{ inputs.soft-fail }}" == "true" ]; then + { + echo "## Markdown Lint Results" + echo "⚠️ **Status**: Warnings (soft-fail)" + echo "" + echo "Markdown linting violations detected but soft-fail is enabled. Review the artifact for details." + } >> "$GITHUB_STEP_SUMMARY" + elif [ "${{ env.MARKDOWN_LINT_FAILED }}" == "true" ]; then { echo "## Markdown Lint Results" echo "❌ **Status**: Failed" diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 84b23c912..37fd180e5 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -389,11 +389,17 @@ jobs: check_result() { local name="$1" local result="$2" + local soft_fail="${3:-false}" + local has_warnings="${4:-}" - if [ "$result" = "success" ]; then + if [ "$result" = "success" ] && [ "$soft_fail" = "true" ] && [ "$has_warnings" = "true" ]; then + echo "⚠️ **$name**: passed with warnings (soft-fail)" >> "$GITHUB_STEP_SUMMARY" + elif [ "$result" = "success" ]; then echo "✅ **$name**: passed" >> "$GITHUB_STEP_SUMMARY" elif [ "$result" = "skipped" ]; then echo "⏭️ **$name**: skipped" >> "$GITHUB_STEP_SUMMARY" + elif [ "$result" = "failure" ] && [ "$soft_fail" = "true" ]; then + echo "⚠️ **$name**: failed (soft-fail, non-blocking)" >> "$GITHUB_STEP_SUMMARY" elif [ "$result" = "failure" ]; then echo "❌ **$name**: failed" >> "$GITHUB_STEP_SUMMARY" FAILED="${FAILED}${name}, " @@ -426,7 +432,7 @@ jobs: check_result "Plugin Validation" "${{ needs.plugin-validation.result }}" check_result "Skill Validation" "${{ needs.skill-validation.result }}" check_result "Link Language Check" "${{ needs.link-lang-check.result }}" - check_result "Markdown Link Check" "${{ needs.markdown-link-check.result }}" + check_result "Markdown Link Check" "${{ needs.markdown-link-check.result }}" "true" "${{ needs.markdown-link-check.outputs.has-warnings }}" check_result "Dependency Pinning" "${{ needs.dependency-pinning-check.result }}" check_result "Workflow Permissions" "${{ needs.workflow-permissions-check.result }}" check_result "Action Version Consistency" "${{ needs.action-version-consistency-scan.result }}" diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 5bbcc6732..143338a00 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -68,7 +68,14 @@ jobs: - name: Add job summary if: always() run: | - if [ "${{ env.SPELL_CHECK_FAILED }}" == "true" ]; then + if [ "${{ env.SPELL_CHECK_FAILED }}" == "true" ] && [ "${{ inputs.soft-fail }}" == "true" ]; then + { + echo "## Spell Check Results" + echo "⚠️ **Status**: Warnings (soft-fail)" + echo "" + echo "Spelling errors were detected but soft-fail is enabled. Review the artifact for details." + } >> "$GITHUB_STEP_SUMMARY" + elif [ "${{ env.SPELL_CHECK_FAILED }}" == "true" ]; then { echo "## Spell Check Results" echo "❌ **Status**: Failed" diff --git a/.github/workflows/table-format.yml b/.github/workflows/table-format.yml index 6842e273c..58b3a8f92 100644 --- a/.github/workflows/table-format.yml +++ b/.github/workflows/table-format.yml @@ -71,7 +71,16 @@ jobs: run: | { echo "## Table Format Check Results" - if [ "${{ env.TABLE_FORMAT_FAILED }}" == "true" ]; then + if [ "${{ env.TABLE_FORMAT_FAILED }}" == "true" ] && [ "${{ inputs.soft-fail }}" == "true" ]; then + echo "⚠️ **Status**: Warnings (soft-fail)" + echo "" + echo "Table formatting issues found but soft-fail is enabled." + echo "" + echo "**To fix manually:**" + echo "1. Run \`npm run format:tables\` locally" + echo "2. Review and commit the changes" + echo "3. Push to update this PR" + elif [ "${{ env.TABLE_FORMAT_FAILED }}" == "true" ]; then echo "❌ **Status**: Failed" echo "" echo "⚠️ **Note**: This check does NOT auto-fix tables." From 701cc3792041690e5cfe88873dbf13c484b0c6ba Mon Sep 17 00:00:00 2001 From: jkim323 Date: Tue, 16 Jun 2026 16:56:00 -0700 Subject: [PATCH 5/5] add validation gate --- .github/workflows/release-stable.yml | 77 ++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-stable.yml b/.github/workflows/release-stable.yml index f7e37c37a..344beea00 100644 --- a/.github/workflows/release-stable.yml +++ b/.github/workflows/release-stable.yml @@ -159,21 +159,88 @@ jobs: matrix: directory: ${{ fromJson(needs.discover-python-projects.outputs.directories) }} - release-please: - name: Release Please + validation-gate: + name: Validation Gate + if: always() needs: - spell-check - markdown-lint - table-format - dependency-pinning-scan + - action-version-consistency-scan - gitleaks-scan - pester-tests - docusaurus-tests + - discover-python-projects - python-lint - pytest - # Allow release-please to run when conditional CI jobs (python-lint, - # pytest) are skipped. Block only on actual failures or cancellations. - if: ${{ !cancelled() && !failure() }} + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Check job results + shell: bash + run: | + { + echo "## Validation Gate Summary" + echo "" + } >> "$GITHUB_STEP_SUMMARY" + + FAILED="" + + check_result() { + local name="$1" + local result="$2" + + if [ "$result" = "success" ]; then + echo "✅ **$name**: passed" >> "$GITHUB_STEP_SUMMARY" + elif [ "$result" = "skipped" ]; then + echo "⏭️ **$name**: skipped" >> "$GITHUB_STEP_SUMMARY" + elif [ "$result" = "failure" ]; then + echo "❌ **$name**: failed" >> "$GITHUB_STEP_SUMMARY" + FAILED="${FAILED}${name}, " + elif [ "$result" = "cancelled" ]; then + echo "⚠️ **$name**: cancelled" >> "$GITHUB_STEP_SUMMARY" + FAILED="${FAILED}${name} (cancelled), " + else + echo "⚠️ **$name**: ${result}" >> "$GITHUB_STEP_SUMMARY" + FAILED="${FAILED}${name} (${result}), " + fi + } + + check_result "Spell Check" "${{ needs.spell-check.result }}" + check_result "Markdown Lint" "${{ needs.markdown-lint.result }}" + check_result "Table Format" "${{ needs.table-format.result }}" + check_result "Dependency Pinning Scan" "${{ needs.dependency-pinning-scan.result }}" + check_result "Action Version Consistency" "${{ needs.action-version-consistency-scan.result }}" + check_result "Gitleaks" "${{ needs.gitleaks-scan.result }}" + check_result "PowerShell Tests" "${{ needs.pester-tests.result }}" + check_result "Docusaurus Tests" "${{ needs.docusaurus-tests.result }}" + check_result "Discover Python Projects" "${{ needs.discover-python-projects.result }}" + check_result "Python Lint" "${{ needs.python-lint.result }}" + check_result "Python Tests" "${{ needs.pytest.result }}" + + if [ -n "$FAILED" ]; then + { + echo "" + echo "---" + echo "❌ **Validation failed**: ${FAILED%, }" + } >> "$GITHUB_STEP_SUMMARY" + echo "One or more required checks failed: ${FAILED%, }" + exit 1 + fi + + { + echo "" + echo "---" + echo "✅ **All validations passed**" + } >> "$GITHUB_STEP_SUMMARY" + + release-please: + name: Release Please + needs: + - validation-gate + if: ${{ success() }} runs-on: ubuntu-latest outputs: release_created: ${{ steps.release.outputs.release_created }}