From 416538aac9d691c2914666352a68c23ba828618e Mon Sep 17 00:00:00 2001 From: mahmoud karzoun <135722882+mkarson1997@users.noreply.github.com> Date: Sat, 5 Sep 2026 14:55:33 +0300 Subject: [PATCH 1/5] ci: add stable aggregate quality gate --- .github/workflows/ci.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4ed095..b73dcf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,3 +52,20 @@ jobs: - name: Build run: npm run build + + ci-gate: + name: CI Gate + if: ${{ always() }} + needs: verify + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - name: Require successful verification matrix + env: + VERIFY_RESULT: ${{ needs.verify.result }} + run: | + if [ "$VERIFY_RESULT" != "success" ]; then + echo "Verification matrix result: $VERIFY_RESULT" + exit 1 + fi + echo "Verification matrix passed." From 88c890e9061fa355f465aa2c34006e79c7c2e460 Mon Sep 17 00:00:00 2001 From: mahmoud karzoun <135722882+mkarson1997@users.noreply.github.com> Date: Sat, 5 Sep 2026 14:57:38 +0300 Subject: [PATCH 2/5] ci: harden aggregate gate against shell injection analysis --- .github/workflows/ci.yml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b73dcf3..eaa8c91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,12 +60,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 2 steps: - - name: Require successful verification matrix - env: - VERIFY_RESULT: ${{ needs.verify.result }} - run: | - if [ "$VERIFY_RESULT" != "success" ]; then - echo "Verification matrix result: $VERIFY_RESULT" - exit 1 - fi - echo "Verification matrix passed." + - name: Confirm successful verification matrix + if: ${{ needs.verify.result == 'success' }} + run: echo "Verification matrix passed." + + - name: Fail when verification did not succeed + if: ${{ needs.verify.result != 'success' }} + run: exit 1 From 83f37e7a7b8d773c0884f4bdeeddf7d82255c350 Mon Sep 17 00:00:00 2001 From: mahmoud karzoun <135722882+mkarson1997@users.noreply.github.com> Date: Sat, 5 Sep 2026 14:58:18 +0300 Subject: [PATCH 3/5] chore: add temporary Sonar diagnostics --- .github/workflows/sonar-diagnostics.yml | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/sonar-diagnostics.yml diff --git a/.github/workflows/sonar-diagnostics.yml b/.github/workflows/sonar-diagnostics.yml new file mode 100644 index 0000000..b4744de --- /dev/null +++ b/.github/workflows/sonar-diagnostics.yml @@ -0,0 +1,35 @@ +name: Temporary Sonar diagnostics + +on: + push: + branches: [chore/stable-ci-gate] + +permissions: + contents: read + +jobs: + diagnose: + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - name: Query SonarCloud pull-request issues + shell: bash + run: | + set -euo pipefail + curl -fsSL 'https://sonarcloud.io/api/issues/search?componentKeys=mkarson1997_karzoun-flowforge&pullRequest=14&resolved=false&ps=100' -o sonar.json + python - <<'PY' + import json + from pathlib import Path + + data = json.loads(Path('sonar.json').read_text()) + issues = data.get('issues', []) + print(f'issues={len(issues)}') + for issue in issues: + print('RULE=', issue.get('rule')) + print('COMPONENT=', issue.get('component')) + print('LINE=', issue.get('line')) + print('SEVERITY=', issue.get('severity')) + print('TYPE=', issue.get('type')) + print('MESSAGE=', issue.get('message')) + print('---') + PY From 17cc89f78f07814904a44b6e49a98791cfe95291 Mon Sep 17 00:00:00 2001 From: mahmoud karzoun <135722882+mkarson1997@users.noreply.github.com> Date: Sat, 5 Sep 2026 14:58:50 +0300 Subject: [PATCH 4/5] ci: scope workflow permissions to individual jobs --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eaa8c91..850dbb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,11 +6,10 @@ on: pull_request: branches: [main] -permissions: - contents: read - jobs: verify: + permissions: + contents: read runs-on: ubuntu-latest timeout-minutes: 10 strategy: @@ -57,6 +56,7 @@ jobs: name: CI Gate if: ${{ always() }} needs: verify + permissions: {} runs-on: ubuntu-latest timeout-minutes: 2 steps: From 72b16d8afa1fc0c97e678f70e22af91949d51508 Mon Sep 17 00:00:00 2001 From: mahmoud karzoun <135722882+mkarson1997@users.noreply.github.com> Date: Sat, 5 Sep 2026 14:59:22 +0300 Subject: [PATCH 5/5] chore: remove temporary Sonar diagnostics --- .github/workflows/sonar-diagnostics.yml | 35 ------------------------- 1 file changed, 35 deletions(-) delete mode 100644 .github/workflows/sonar-diagnostics.yml diff --git a/.github/workflows/sonar-diagnostics.yml b/.github/workflows/sonar-diagnostics.yml deleted file mode 100644 index b4744de..0000000 --- a/.github/workflows/sonar-diagnostics.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Temporary Sonar diagnostics - -on: - push: - branches: [chore/stable-ci-gate] - -permissions: - contents: read - -jobs: - diagnose: - runs-on: ubuntu-latest - timeout-minutes: 3 - steps: - - name: Query SonarCloud pull-request issues - shell: bash - run: | - set -euo pipefail - curl -fsSL 'https://sonarcloud.io/api/issues/search?componentKeys=mkarson1997_karzoun-flowforge&pullRequest=14&resolved=false&ps=100' -o sonar.json - python - <<'PY' - import json - from pathlib import Path - - data = json.loads(Path('sonar.json').read_text()) - issues = data.get('issues', []) - print(f'issues={len(issues)}') - for issue in issues: - print('RULE=', issue.get('rule')) - print('COMPONENT=', issue.get('component')) - print('LINE=', issue.get('line')) - print('SEVERITY=', issue.get('severity')) - print('TYPE=', issue.get('type')) - print('MESSAGE=', issue.get('message')) - print('---') - PY