Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .github/workflows/actions-poll-analyzer-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Actions poll analyzer coverage

on:
pull_request:

permissions:
contents: read

concurrency:
group: actions-poll-analyzer-coverage-${{ github.repository }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
exact-head-coverage:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
steps:
- name: Fail closed without a pull request number
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
if [ -z "${PR_NUMBER}" ]; then
echo "Indirect invocation without a pull request number is not allowed."
exit 1
fi

- name: Checkout exact pull request head
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.13'

- name: Install hash-locked test dependencies
run: python -m pip install --disable-pip-version-check --no-cache-dir --require-hashes -r requirements-test.txt

- name: Checkout verified Coverage.py source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: coveragepy/coveragepy
ref: 4c0e7ff425ecbb33e2b994b41118a71eb4e39021 # 7.15.4
path: .tools/coveragepy
persist-credentials: false

- name: Verify 100% analyzer statements and branches
env:
PYTHONPATH: ${{ github.workspace }}/.tools/coveragepy:${{ github.workspace }}
run: |
set -euo pipefail
python -m coverage erase
python -m coverage run --branch \
--source=appguardrail_core.actions_poll_analyzer \
-m pytest -q \
tests/test_actions_poll_structural_analyzer.py \
tests/test_github_actions_poll_bounds.py \
tests/test_github_actions_poll_bound_control_flow_regression.py \
tests/test_github_actions_poll_bound_aliases.py \
tests/test_github_actions_poll_bound_bare_exit.py \
tests/test_github_actions_poll_bound_command_whitespace.py \
tests/test_github_actions_poll_bound_current_head_regressions.py \
tests/test_github_actions_poll_bound_late_initialization.py \
tests/test_github_actions_poll_bound_mixed_safety.py \
tests/test_github_actions_poll_bound_review_20260902.py \
tests/test_github_actions_poll_bound_review_precision.py \
tests/test_github_actions_poll_bound_state_reset.py \
tests/test_github_actions_poll_bound_unreachable_exit.py \
tests/test_github_actions_poll_bounds_large_job.py \
tests/test_github_actions_poll_control_flow_review.py \
tests/test_github_actions_poll_deadline_tightening.py
python -m coverage report \
--include=appguardrail_core/actions_poll_analyzer.py \
--precision=2 \
--show-missing \
--fail-under=100

- name: Verify exact unrounded statement coverage
run: |
python -m scripts.ci.verify_module_coverage \
--module appguardrail_core/actions_poll_analyzer.py \
--test tests/test_actions_poll_structural_analyzer.py

- name: Compile production and test modules
run: >-
python -m compileall -q
appguardrail_core/actions_poll_analyzer.py
tests/test_actions_poll_structural_analyzer.py
tests/test_github_actions_poll_bounds.py
tests/test_github_actions_poll_bound_control_flow_regression.py
3 changes: 3 additions & 0 deletions CHANGELOG.d/1087-actions-poll-structural-analyzer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Security

- Add a bounded structural GitHub Actions + shell analyzer that classifies transport-only polling loops by causal control flow (loop-local initialization, forward `-gt`/`-ge` total bounds, reachable fail-closed exits, and statically positive owning-job timeouts) while preserving the packaged `github-actions-transport-only-poll-bound` and `github-actions-transport-failure-budget-poll-bound` identities as migration oracles. Helper loops, sibling-job timeouts, reversed comparisons, unreachable exits, and quoted or comment text cannot donate safety. See issue #1087 and ADR-0009 (Proposed).
Loading