feat: add contributor CI workflow for fork-friendly testing#192
feat: add contributor CI workflow for fork-friendly testing#192abtreece wants to merge 9 commits into
Conversation
Add a credentialless CI workflow that runs on contributor forks and PRs, enabling third-party contributors to validate their changes without access to project infrastructure. - Contributor CI workflow (ci-cd-contributor) builds Ruby packages for two representative distributions (Ubuntu 24.04 and EL 9) with applicable variants and runs smoke tests - ok-to-test label gate lets maintainers trigger the full CI pipeline; a label guard workflow removes the label on new pushes, requiring re-review before re-triggering - Main CI/CD workflow restricted to upstream repository only - Respects variant_exclusions from config.yml (skips malloctrim for Ruby >= 3.3) - Test script fixes: createrepo -> createrepo_c, added adduser package - Updated CONTRIBUTING.md with fork CI and local build/test docs
b39e09f to
c5c0ec4
Compare
noahssarcastic
left a comment
There was a problem hiding this comment.
Looks good, reviewed with respect to pull_request and pull_request_target and all actions are safe from "pwn request" PR's. Added a couple of nitpick type things, we may want to call out the use of pull_request and pull_request_target and other guard-rails in comment to ensure they are not accidentally removed or modified.
| with: | ||
| ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }} |
There was a problem hiding this comment.
Don't we need to do this on all jobs?
There was a problem hiding this comment.
Good catch — yes. check_workflow_uptodate had a bare actions/checkout@v4 with no ref: override, so under pull_request_target it was validating the base branch's generated YAML and silently passing regardless of what the PR changed.
Added the same ref: override AND the ok-to-test label gate used by determine_necessary_jobs, so the check now actually validates PR-head contents and only runs after a maintainer has labeled the PR (69f5211).
Audited the rest of ci-cd-main.yml.erb — check_workflow_uptodate was the only other job using actions/checkout directly; everything else uses workflow_call and inherits behavior from the called workflows.
There was a problem hiding this comment.
everything else uses workflow_call and inherits behavior from the called workflows.
Then don't we need to update those workflows too?
Deduplicates the distribution entry mapping between `distributions` and `contributor_distributions`, and fixes a memoization break where `return [] if names.nil?` exited the method without assigning the `||= begin` block.
Previously relied on `ruby_package_versions.first`, which in turn depended on the order of `minor_version_packages` and `tiny_version_packages` in `config.yml`. Use `max_by` with `Gem::Version` so the result is deterministic regardless of config ordering. Considered sorting the full `ruby_package_versions` list (the broader fix Noah suggested), but that interleaves minor/tiny entries and produces a ~9000-line rendered-YAML diff with no functional change to which version is "latest". Targeting `latest_ruby_package_version` directly addresses the robustness concern with minimal blast radius.
The previous guard `event_name == 'pull_request' || repository != upstream` fired for both fork PRs AND same-repo PRs, causing the contributor workflow to run alongside ci-cd-main on internal branches and duplicating every build. Tighten the condition so the workflow only runs when either (a) it's executing in a fork's own repo, or (b) it's executing in upstream for a PR whose head is in a fork.
Prevents stuck runners from lingering at the default 360-minute timeout. build_packages (60m) and test_packages (30m) already had explicit timeouts; this adds 10m for lint and 30m for build_images.
Splits the contributor workflow's previously-monolithic build_images and build_packages jobs into per-distro matrix jobs, and extracts distro-agnostic packages (rbenv, common) into a separate build_common_packages job that runs in parallel. Also sets retention-days: 1 on all contributor artifacts -- they're purely job-to-job intermediate state and don't need the default 90-day retention.
Pins all third-party action references in the workflows introduced by this PR to commit SHAs, with a trailing tag comment for readability. Mitigates supply-chain risk from mutable tag re-pointing in workflows that run untrusted contributor code. Also adds .github/dependabot.yml so the github-actions ecosystem tracks SHA updates automatically. Scope: ci-cd-contributor.yml.erb and ci-cd-label-guard.yml. Pinning the pre-existing workflows (main, prepare, build-packages-N, publish-test-*) is out of scope here and can land separately.
…R head Under pull_request_target the bare actions/checkout@v4 was checking out the base branch, so the "is the generated YAML up-to-date with the ERB?" check silently passed regardless of what the PR changed, making the check meaningless for fork PRs. Add the same ref: override and ok-to-test label gate used by determine_necessary_jobs so the check actually validates PR-head contents, and only runs after a maintainer has labeled the PR.
…flow headers Adds a short header comment to ci-cd-main, ci-cd-contributor, and ci-cd-label-guard describing how the three files combine to form the fork-PR security boundary. A future change to any single file (e.g., flipping pull_request_target to pull_request, removing the label gate, renaming the ok-to-test label) silently breaks the model otherwise.
|
Pushed 8 commits addressing the inline feedback. Summary:
Heads-up on CI: the new triggers ( Ready for re-review. |
|
All right, there's just one open comment left. |
Summary
Adds a credentialless CI workflow that runs on contributor forks and PRs, enabling third-party contributors to validate their changes without access to project infrastructure.
ci-cd-contributor): Builds Ruby packages for two representative distributions (Ubuntu 24.04 and EL 9) with applicable variants and runs smoke tests. No cloud credentials or special setup needed.ok-to-testlabel gate: Maintainers can add theok-to-testlabel to trigger the full CI pipeline (all distros, test publishing) against a PR. A label guard workflow automatically removes the label when new commits are pushed, requiring re-review before re-triggering.github.repositoryto avoid running on forks.variant_exclusionsfrom config.yml (e.g., skips malloctrim for Ruby >= 3.3).createrepo→createrepo_cin RPM test prep, addedadduserpackage for DEB tests.Closes #54
Test plan
ok-to-testlabel triggers full pipeline on PRok-to-teston new push to PR./internal-scripts/generate-ci-cd-yaml.rb)