OSAC-870: Add CaaS E2E caller workflow - #442
Conversation
Add a cross-repo caller workflow that invokes the reusable CaaS E2E workflow in osac-test-infra. On PRs, builds the osac-aap execution environment image from the PR branch via ansible-builder and injects it via the aap.bootstrap.image Helm value path, then runs the CaaS E2E test suite against a live cluster with the PR's code deployed. Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Trey West <trwest@redhat.com>
|
@trewest: This pull request references OSAC-870 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
WalkthroughAdds an E2E CaaS full-install GitHub Actions workflow with pull-request and manual triggers, documentation-only change filtering, reusable workflow delegation, fork parameter forwarding, concurrency cancellation, and an always-run failure gate. ChangesE2E CaaS validation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 11✅ Passed checks (11 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: trewest The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/retest |
|
Re-triggered failed runs:
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/e2e-caas-full-install.yml:
- Around line 50-66: Add SAST and SCA scanning plus Sigstore/cosign image
signing and verification gates to the e2e-caas-full-install workflow, or pass
equivalent enforcement through the referenced reusable workflow before
deployment. Ensure the existing e2e-caas-full-install job cannot proceed unless
scans pass and the built artifact is successfully signed and verified.
- Around line 50-53: Update the reusable workflow reference in the
e2e-caas-full-install job to replace the mutable `@main` ref with the vetted
40-character commit SHA, preserving the existing workflow path and job
conditions.
- Line 47: Update the path exclusion pattern in the workflow trigger to
recursively exclude Markdown files at every directory depth. Replace the
root-only negation alongside the existing include/exclusion patterns with the
recursive `**/*.md` form, preserving all other workflow paths unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b9d02b31-84bd-4175-afa3-0a29027c9cd2
📒 Files selected for processing (1)
.github/workflows/e2e-caas-full-install.yml
| - '**' | ||
| - '!OWNERS' | ||
| - '!LICENSE' | ||
| - '!*.md' |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate workflow =="
fd -a 'e2e-caas-full-install\.yml$' . || true
echo "== relevant workflow lines =="
if [ -f .github/workflows/e2e-caas-full-install.yml ]; then
nl -ba .github/workflows/e2e-caas-full-install.yml | sed -n '1,120p'
fi
echo "== path-filter usage/search =="
rg -n "paths-filter|!.*\*\.md|excluded|paths" .github/workflows -g '*.yml' -g '*.yaml' || true
echo "== git status/diff context if available =="
git diff --stat || true
git diff -- .github/workflows/e2e-caas-full-install.yml | sed -n '1,160p' || trueRepository: osac-project/osac-aap
Length of output: 251
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files of interest =="
git ls-files . | grep -E '(^|/)(\.gitingore|README|\.github/workflows/e2e-caas-full-install\.yml)' || true
echo "== locate workflow =="
find . -type f -name 'e2e-caas-full-install.yml' -print || true
workflow='.github/workflows/e2e-caas-full-install.yml'
if [ -f "$workflow" ]; then
echo "== workflow line count =="
wc -l "$workflow"
echo "== first 180 lines =="
awk '{printf "%6d\t%s\n", NR, $0}' "$workflow" | sed -n '1,180p'
echo "== path-filter occurrences =="
grep -nE 'paths-filter|exclude|include|\!.*\*\.md|\*\.md|paths' "$workflow" || true
fi
echo "== all workflow path-filter occurrences =="
find .github/workflows -type f \( -name '*.yml' -o -name '*.yaml' \) -print | while read -r f; do
if grep -qE 'paths-filter|\!.*\*\.md|paths:' "$f"; then
printf '\n-- %s --\n' "$f"
grep -nE 'paths-filter|\!.*\*\.md|paths:' "$f" || true
fi
doneRepository: osac-project/osac-aap
Length of output: 16016
🌐 Web query:
dorny/paths-filter v4.0.2 README glob patterns ** single-star exclude .md
💡 Result:
In the dorny/paths-filter GitHub Action, glob patterns are evaluated by the underlying picomatch library [1]. To exclude specific file types like.md (Markdown files) while including others, you should use negation patterns (prefixed with!), but be aware of how the action's predicate-quantifier interacts with these patterns [2][3][4]. Key points regarding pattern matching and exclusion: 1. Default Behavior (predicate-quantifier: some): By default, the action uses "OR" logic [5]. If you provide a list of patterns like ['', '!/.md'], any file matching either pattern (which is effectively everything) will be included, because the negative pattern alone does not implicitly exclude files from a positive set unless structured correctly or used with a different quantifier [5][4]. Recent updates to the action (specifically PR #310) have improved how bare negation patterns are handled in the default quantifier mode to behave more like.gitignore rules [4]. 2. Using 'every' for Exclusions: If you need to strictly exclude a file type, the recommended approach in the documentation is to set predicate-quantifier to 'every' [2][3]. This changes the logic so that all patterns must match for a file to be included [2][3]. Example using 'every': filters: | my-filter: - 'src/' - '!/.md' predicate-quantifier: 'every' In this configuration, a file must match 'src/' AND NOT match '/.md' to be included [3]. 3. Glob Pattern Tips: * Single-star in picomatch is often used to match directories and files recursively [1]. * Ensure your patterns are quoted (e.g., '!/.md') to avoid YAML parsing errors, especially if they start with special characters like * or! [6][2]. * If you find that a negation pattern is not working as expected (e.g., it is still matching files you intend to exclude), double-check if your positive patterns are broad enough and if the negation pattern is correctly scoped [5][1]. If a pattern like '!(/.md)' does not work, it is often because of how the matcher treats file separators; using '/.md' is generally safer for recursive exclusion [1].
Citations:
- 1: Excluding file via negation is not working as expected dorny/paths-filter#135
- 2: https://github.com/dorny/paths-filter
- 3: https://github.com/marketplace/actions/paths-changes-filter
- 4: Honor negation patterns under default predicate quantifier dorny/paths-filter#310
- 5: Ignore pattern ignored? dorny/paths-filter#97
- 6: dorny/paths-filter@v4.0.1...v4.0.2
🌐 Web query:
picomatch globstar single star dotdot directories directory separator pattern semantics
💡 Result:
In Picomatch, glob pattern semantics distinguish clearly between single stars (), globstars, and their behavior regarding path separators and directory segments [1][2]. Single Star () The single star matches any character zero or more times, but it specifically excludes path separators [1][3]. Consequently, a single star cannot match across directory boundaries; it is restricted to a single path segment [2][4]. By default, it also does not match hidden files or directories ("dotfiles") unless the dot option is explicitly enabled [1][5]. Globstar The globstar is designed for recursive directory matching [2][4]. It matches any character zero or more times, including path separators, allowing it to traverse nested directories [1][2]. However, the globstar has specific constraints to ensure predictable behavior: 1. It only matches path separators when it constitutes the entire path segment [1][3]. For example, a pattern like foo/bar is treated as foo*/bar, and foo/ab/bar is treated as foo/ab/bar [1][6]. 2. Any sequence of more than two consecutive stars in a single path segment is automatically treated as a single star [1][4]. Thus, foo//bar is equivalent to foo/*/bar [1][3]. Key Semantics and Differences - Path Separators: The globstar is the only way to match across path separators in Picomatch, distinguishing it from some other shell-like implementations [2][4]. Notably, Picomatch does not follow Bash's behavior where a simple * might match across directories (e.g., matching foo/bar/baz with *) [1][6]. - Directory Separators: Picomatch supports both forward slashes (/) and, when the windows option is enabled, backslashes () as valid path separators [1][5][2]. - Bash Compatibility: While Picomatch is inspired by Bash, it intentionally deviates from Bash's matching rules regarding the single star's ability to cross directory boundaries [1][6]. If strict Bash-like behavior is required, the bash option can be enabled, which—among other things—treats single stars as globstars [1][5]. These semantics ensure that recursive matching is explicit (using) while segment-restricted matching remains the default for single wildcards [2][4].
Citations:
- 1: https://github.com/micromatch/picomatch
- 2: https://deepwiki.com/micromatch/picomatch/3-glob-pattern-syntax
- 3: https://github.com/micromatch/picomatch/blob/HEAD/.verb.md
- 4: https://deepwiki.com/micromatch/picomatch/3.1-basic-patterns
- 5: https://www.npmjs.com/package/picomatch
- 6: https://github.com/micromatch/picomatch/blob/refs/heads/master/README.md
Exclude nested Markdown files too.
!*.md only covers root-level Markdown files because single wildcards do not cross path separators. A docs-only change under a nested directory can still satisfy the include/exclusion predicates and run this E2E workflow; use !**/*.md for the recursive negation.
Proposed fix
- - '!*.md'
+ - '!**/*.md'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - '!*.md' | |
| - '!**/*.md' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/e2e-caas-full-install.yml at line 47, Update the path
exclusion pattern in the workflow trigger to recursively exclude Markdown files
at every directory depth. Replace the root-only negation alongside the existing
include/exclusion patterns with the recursive `**/*.md` form, preserving all
other workflow paths unchanged.
| e2e-caas-full-install: | ||
| needs: changes | ||
| if: needs.changes.outputs.should-run == 'true' | ||
| uses: osac-project/osac-test-infra/.github/workflows/e2e-caas-full-install.yml@main |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow lines =="
sed -n '1,120p' .github/workflows/e2e-caas-full-install.yml | cat -n
echo
echo "== reusable workflow references in .github/workflows =="
rg -n "uses:\s*[^#]+@[^#]+" .github/workflows || trueRepository: osac-project/osac-aap
Length of output: 5821
🌐 Web query:
GitHub Actions reusable workflows SHA references safest option workflow syntax
💡 Result:
For GitHub Actions reusable workflows, the safest option for referencing is a full-length commit SHA [1][2][3]. When you use a reusable workflow, you reference it using the syntax: {owner}/{repo}/.github/workflows/{filename}@{ref} [1] The {ref} can be a branch name, a release tag, or a commit SHA [1][4]. While branch names and tags are convenient because they allow for automatic updates, they are mutable—meaning a maintainer or an attacker who compromises the repository could change the code pointed to by that reference without notice [5][4][6]. Key takeaways for security and workflow stability: 1. Safest Choice (Full-Length SHA): Pinning to a full-length commit SHA is the only way to ensure the workflow is immutable [2][5][4]. This protects against supply chain attacks where a malicious actor replaces the code behind a tag or branch name [5][6]. 2. Practical Maintenance: Because updating SHA pins manually is labor-intensive, it is best practice to use dependency management tools like Dependabot or Renovate to automatically create pull requests when a newer version (tag) is available [5]. You can also keep the human-readable tag in a comment alongside the SHA for clarity (e.g., uses: owner/repo/.github/workflows/file.yml@abcdef123456... # v1.0.0) [5][6]. 3. Same-Repository Workflows: If your reusable workflow is stored in the same repository as the caller workflow, use the syntax./.github/workflows/{filename} or $/.github/workflows/{filename} [1]. In this case, the reusable workflow is implicitly pinned to the same commit as the caller, and no SHA reference is needed or allowed [1][6]. 4. Transitive Security: Remember that a reusable workflow is a single point of compromise [5][7]. Ensure that the reusable workflow itself also pins all actions it calls to full-length SHAs, as your callers will inherit these dependencies invisibly [5][7]. Organizations with higher security requirements should enable the repository or organization-level policy to require actions (including reusable workflows) to be pinned to a full-length commit SHA where applicable [2][7].
Citations:
- 1: https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows
- 2: https://docs.github.com/en/actions/reference/security/secure-use
- 3: https://adaptive-enforcement-lab.com/secure/github-actions-security/workflows/reusable/caller-validation-pinning/
- 4: http://msx.no/Coding-Standards/GitHub-Actions/
- 5: https://safeguard.sh/resources/blog/securing-github-actions-reusable-workflows-at-scale
- 6: https://github.com/ActionsCI/reusable-workflows
- 7: https://www.systemshardening.com/articles/cicd/github-actions-reusable-workflow-pinning-audit/
Pin the reusable workflow to a full commit SHA.
This pull-request-triggered workflow calls osac-project/osac-test-infra/.github/workflows/e2e-caas-full-install.yml@main, and branch refs are mutable. Pin to a vetted 40-character commit SHA and update it intentionally.
🧰 Tools
🪛 zizmor (1.28.0)
[error] 53-53: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/e2e-caas-full-install.yml around lines 50 - 53, Update the
reusable workflow reference in the e2e-caas-full-install job to replace the
mutable `@main` ref with the vetted 40-character commit SHA, preserving the
existing workflow path and job conditions.
Sources: Path instructions, Linters/SAST tools
| e2e-caas-full-install: | ||
| needs: changes | ||
| if: needs.changes.outputs.should-run == 'true' | ||
| uses: osac-project/osac-test-infra/.github/workflows/e2e-caas-full-install.yml@main | ||
| with: | ||
| test-suite: ${{ inputs.test-suite || 'caas' }} | ||
| test-filter: ${{ inputs.test-filter || '' }} | ||
| component-repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }} | ||
| component-ref: ${{ github.event.pull_request.head.ref || github.ref_name }} | ||
| component-image-key: aap.bootstrap.image | ||
| component-build-type: ansible-builder | ||
| component-containerfile: execution-environment/execution-environment.yaml | ||
| fork-pr-author-association: ${{ github.event.pull_request.head.repo.fork && github.event.pull_request.author_association || '' }} | ||
| fork-pr-author: ${{ github.event.pull_request.head.repo.fork && github.event.pull_request.user.login || '' }} | ||
| pr-number: ${{ github.event.pull_request.number }} | ||
| test-infra-repository: osac-project/osac-test-infra | ||
| test-infra-ref: ${{ inputs.test-infra-ref || 'main' }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow files =="
git ls-files .github/workflows || true
echo
echo "== target workflow excerpt =="
if [ -f .github/workflows/e2e-caas-full-install.yml ]; then
nl -ba .github/workflows/e2e-caas-full-install.yml | sed -n '1,140p'
else
echo "target workflow not found"
fi
echo
echo "== references to security/signing/scan scans in workflows =="
rg -n -i 'sast|sca|scan|sigstore|cosign|attest|verify|artifact|sign|checksum|scorecard|dependency|dependabot|actionlint|maven|npm audit|pysafety|bandit|trivy|grype|clair|hadolint|gosec' .github/workflows || trueRepository: osac-project/osac-aap
Length of output: 693
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== target workflow excerpt =="
if [ -f .github/workflows/e2e-caas-full-install.yml ]; then
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/e2e-caas-full-install.yml | sed -n '1,160p'
else
echo "target workflow not found"
fi
echo
echo "== referenced reusable workflow files if present =="
for f in .github/workflows/e2e-caas-full-install.yml; do
echo "-- $f --"
grep -Ehn '^[^[:space:]]+#|uses:|steps:|run:|permissions:|if:' "$f" || true
done
echo
echo "== all workflow occurrences of security/signing/scan terms =="
rg -n -i 'sast|sca|scan|sigstore|cosign|attest|verify|artifact|sign|checksum|scorecard|dependency|dependabot|actionlint|maven|npm audit|pysafety|bandit|trivy|grype|clair|hadolint|gosec' .github/workflows || trueRepository: osac-project/osac-aap
Length of output: 4519
Add required scan and signing gates.
This workflow delegates a PR image build/run through osac-project/osac-test-infra but has no SAST/SCA step and no Sigstore/cosign artifact signing/verification gate. Add those controls here or enforce them through the reusable workflow before deployment.
🧰 Tools
🪛 zizmor (1.28.0)
[error] 53-53: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/e2e-caas-full-install.yml around lines 50 - 66, Add SAST
and SCA scanning plus Sigstore/cosign image signing and verification gates to
the e2e-caas-full-install workflow, or pass equivalent enforcement through the
referenced reusable workflow before deployment. Ensure the existing
e2e-caas-full-install job cannot proceed unless scans pass and the built
artifact is successfully signed and verified.
Source: Path instructions
OSAC-870: Add CaaS E2E caller workflow
Jira: https://redhat.atlassian.net/browse/OSAC-870
Summary
Adds a cross-repo caller workflow that invokes the reusable CaaS E2E workflow in
osac-test-infra. Same pattern as the BMaaS presubmit jobs.
Related PRs
Testing
workflow_dispatchfrom the branch to validate the workflow runsAssisted-by: Claude Code noreply@anthropic.com
Summary by CodeRabbit
New Features
Bug Fixes