# C9 - control-flow: timeout-minutes, continue-on-error, concurrency (parse-only) # Reusable workflow invoked by 00-suite-runner.yml. Verifies three control-flow # behaviors: # 1. step-level timeout-minutes kills a runaway step (tested via continue-on-error # so the job stays green; outcome is asserted as 'failure' to prove the # timeout fired). # 2. continue-on-error makes a step's conclusion 'success' despite outcome # 'failure', verified by a dependent job. # 3. concurrency is parsed and accepted only; actual cancellation is # server-side and not self-asserted (see README manual checklist). name: 09-control-flow on: [push, workflow_dispatch] permissions: contents: read # concurrency: parse-and-accept only. Actual cancellation is server-side and NOT # self-asserted - see README manual checklist. concurrency: group: cf-${{ github.ref }} cancel-in-progress: false jobs: control-flow-test: name: timeout + continue-on-error + concurrency runs-on: ubuntu-24.04 timeout-minutes: 5 steps: - uses: actions/checkout@v4 # --- continue-on-error test --- - name: tolerated failure id: flaky continue-on-error: true run: exit 1 - name: assert continue-on-error outcome and conclusion if: always() run: | source lib/assert.sh assert_eq "${{ steps.flaky.outcome }}" "failure" "flaky step outcome is failure" assert_eq "${{ steps.flaky.conclusion }}" "success" "flaky step conclusion is success (tolerated)" # --- step-level timeout-minutes test --- # Uses STEP-level timeout-minutes (not job-level) so a killed step # doesn't cascade the job to failure. continue-on-error keeps the # job green; the outcome is asserted as 'failure' to prove the # timeout actually fired. - name: step that should timeout id: timeout-step timeout-minutes: 1 continue-on-error: true run: sleep 90 - name: assert step was killed by timeout if: always() run: | source lib/assert.sh if [ "${{ steps.timeout-step.outcome }}" == "failure" ]; then assert_eq "timed-out" "timed-out" "step killed by timeout-minutes (outcome: ${{ steps.timeout-step.outcome }})" else echo "::warning::step-level timeout-minutes not enforced by this runner (outcome: ${{ steps.timeout-step.outcome }}); job-level timeout enforcement is documented in act source" assert_eq "${{ steps.timeout-step.outcome }}" "failure" "step killed by timeout-minutes" fi