feat(github): add GitHub App authentication for self-hosted runner registration#860
feat(github): add GitHub App authentication for self-hosted runner registration#860adrianriobo wants to merge 4 commits into
Conversation
|
Important Review skippedToo many files! This PR contains 192 files, which is 92 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (192)
You can disable this status message by setting the 📝 WalkthroughWalkthroughChangesGitHub Runner Authentication
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant SetupRunner
participant PulumiGitHub
participant GitHub
participant DeploymentTarget
CLI->>DeploymentTarget: Provide GitHub runner arguments
DeploymentTarget->>SetupRunner: Initialize runner
SetupRunner->>PulumiGitHub: Create App provider
PulumiGitHub->>GitHub: Request registration token
GitHub-->>SetupRunner: Return registration token
SetupRunner-->>DeploymentTarget: Store token
DeploymentTarget->>DeploymentTarget: Generate runner userdata
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
oci/Containerfile (1)
14-19: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRestore the vendored
pulumi-githubSDK
go.modandvendor/modules.txtstill referencegithub.com/pulumi/pulumi-github/sdk/v6, but the correspondingvendor/github.com/pulumi/pulumi-github/sources are missing. Regeneratevendor/and commit those files somake buildcan resolve imports under-mod=vendor.🤖 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 `@oci/Containerfile` around lines 14 - 19, Regenerate the Go vendor directory so the pulumi-github SDK referenced by go.mod and vendor/modules.txt is restored under vendor/github.com/pulumi/pulumi-github/, including all required source files and metadata. Commit the regenerated vendor contents and keep the existing make build flow unchanged.Sources: Linters/SAST tools, Pipeline failures
🤖 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 `@docs/self-hosted-runner.md`:
- Line 16: Update the authentication precedence description in the self-hosted
runner documentation to match GithubRunnerArgs: select GitHub App authentication
first, then the explicit --ghactions-runner-token value, and generate a token
from GITHUB_TOKEN only when no explicit token is supplied.
- Around line 24-25: Update the prerequisites in the self-hosted runner
documentation to describe repository-level GitHub App permissions and
installation only. Remove the organization-level permission and runner wording
from the entries associated with the --ghactions-runner-repo setup, leaving the
repository-scoped requirements unchanged.
---
Outside diff comments:
In `@oci/Containerfile`:
- Around line 14-19: Regenerate the Go vendor directory so the pulumi-github SDK
referenced by go.mod and vendor/modules.txt is restored under
vendor/github.com/pulumi/pulumi-github/, including all required source files and
metadata. Commit the regenerated vendor contents and keep the existing make
build flow 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: Organization UI
Review profile: CHILL
Plan: Enterprise
Run ID: 97347c14-74ad-4aab-8ac6-a8356f35750a
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (15)
cmd/mapt/cmd/params/params.godocs/self-hosted-runner.mdgo.modoci/Containerfilepkg/integrations/github/api.gopkg/integrations/github/ghrunner.gopkg/integrations/github/types.gopkg/provider/aws/modules/mac/machine/setup/setup.gopkg/provider/azure/action/windows/windows.gopkg/provider/ibmcloud/action/ibm-power/ibm-power.gopkg/provider/ibmcloud/action/ibm-z/ibm-z.gopkg/target/host/fedora/fedora.gopkg/target/host/rhel/cloud-config.gopkg/target/host/windows-server/windows-server.govendor/modules.txt
…gistration Replace the short-lived PAT approach with GitHub App credentials (App ID, installation ID, private key PEM). The Pulumi GitHub provider is instantiated with AppAuth inside the deployment context and calls GetActionsRegistrationToken to fetch a fresh registration token at deploy time — no pre-generated tokens or manual JWT handling required. Backward compatibility is preserved: the existing --ghactions-runner-token and GITHUB_TOKEN (PAT) paths continue to work unchanged. - Add AppID, InstallationID, PrivateKeyPath to GithubRunnerArgs - Add SetupRunner() using pulumi-github/sdk/v6 provider with AppAuth - Add --ghactions-app-id, --ghactions-app-installation-id, --ghactions-app-private-key flags - Call SetupRunner() before user-data generation in all 7 providers (rhel, fedora, windows-server, mac, azure-windows, ibm-power, ibm-z) - Add pulumi-github/sdk/v6 v6.14.0 to go.mod and Containerfile - Update docs/self-hosted-runner.md with all three auth options Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ner.md - Correct authentication precedence to match GithubRunnerArgs: App → explicit token → GITHUB_TOKEN PAT auto-generate - Narrow GitHub App prerequisites to repository scope only; the current implementation uses GetActionsRegistrationToken (repo-level) and has no organisation runner support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add --ghactions-runner-org flag (mutually exclusive with --ghactions-runner-repo) mirroring GitLab's --glrunner-group-id vs --glrunner-project-id pattern. - types.go: add Org field to GithubRunnerArgs - api.go: add GenerateOrgRegistrationToken for PAT path - ghrunner.go: SetupRunner branches on Org vs RepoURL — org path uses GetActionsOrganizationRegistrationToken with provider Owner=org; GetUserDataValues derives registration URL as https://github.com/{org} - params.go: add --ghactions-runner-org flag, mutual exclusivity check, Org field population for all three auth paths - docs: update flag table to include --ghactions-runner-org Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@adrianriobo , it sounds like you're picturing that something or someone would run |
|
My ideal world would be the controller who will check events for workloads on an specific type of runner, it will run automatically mapt create to create and join the runner. In a first phase if we define a set of static (long live) runners this will be executed either by an operator or a pipeline if we define them in a gitops approach |
|
Ok, thanks. gitops approach preferred. |
deekay2310
left a comment
There was a problem hiding this comment.
Looks good, just a handful of nits; nothing blocking.
| } | ||
| args.Token = result.Token | ||
| } else { | ||
| _, repo, _ := splitOwnerRepo(args.RepoURL) |
There was a problem hiding this comment.
The error from splitOwnerRepo is discarded here. It's technically safe today because the same URL was validated at line 135, but if the code paths are ever refactored independently this becomes a silent failure.
| _, repo, _ := splitOwnerRepo(args.RepoURL) | |
| _, repo, err := splitOwnerRepo(args.RepoURL) | |
| if err != nil { | |
| return err | |
| } |
| AppAuth: pulgithub.ProviderAppAuthPtr(&pulgithub.ProviderAppAuthArgs{ | ||
| Id: pulumi.String(args.AppID), | ||
| InstallationId: pulumi.String(args.InstallationID), | ||
| PemFile: pulumi.String(string(pemBytes)), |
There was a problem hiding this comment.
The provider SDK's NewProvider only auto-wraps Token as a secret (see provider.go:51), not AppAuth.PemFile. This means the RSA private key will appear in plaintext in Pulumi state.
| PemFile: pulumi.String(string(pemBytes)), | |
| PemFile: pulumi.ToSecret(pulumi.String(string(pemBytes))).(pulumi.StringInput), |
| "expires_at": "2024-07-12T19:01:48.478+05:30" | ||
| } | ||
| ``` | ||
| 1. Create a GitHub App with the `administration:write` permission on the target repository. |
There was a problem hiding this comment.
For org-level runners (--ghactions-runner-org), the App needs the organization_self_hosted_runners:write permission instead of repo-level administration:write. Since the flags table and code already support the org path, consider something like:
| 1. Create a GitHub App with the `administration:write` permission on the target repository. | |
| 1. Create a GitHub App with the `administration:write` permission (for repository runners) or `organization_self_hosted_runners:write` permission (for organization runners). |
| To deploy a Windows runner on the Azure provider, we can use the following command: | ||
| ### Option B — Personal Access Token (PAT) | ||
|
|
||
| Set the `GITHUB_TOKEN` environment variable to a PAT with `repo` admin scope. `mapt` will call the GitHub API to generate a registration token automatically before deployment. |
There was a problem hiding this comment.
This only covers the repo case. For org-level runners (--ghactions-runner-org), the PAT needs admin:org scope instead of repo admin. The error message in api.go:58 already tells the user this on failure, but it'd be better to document it upfront.
| Set the `GITHUB_TOKEN` environment variable to a PAT with `repo` admin scope. `mapt` will call the GitHub API to generate a registration token automatically before deployment. | |
| Set the `GITHUB_TOKEN` environment variable to a PAT with `repo` scope (for repository runners) or `admin:org` scope (for organization runners). `mapt` will call the GitHub API to generate a registration token automatically before deployment. |
… lifetime Replace hardcoded --ephemeral in ppc64le and s390x runner scripts with a configurable flag. Default is non-ephemeral; pass --ghactions-runner-ephemeral to register a single-job runner that deregisters automatically after one run. Flag is wired through all platforms (linux, darwin, windows, ppc64le, s390x). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
pulumi-github/sdk/v6) is instantiated withAppAuthinside the deployment context and callsGetActionsRegistrationTokenat deploy time — no pre-generated tokens or JWT handling required--ghactions-runner-token(explicit token) andGITHUB_TOKEN(PAT auto-generate) both continue to work unchangedChanges
pkg/integrations/github/types.go— addAppID,InstallationID,PrivateKeyPathtoGithubRunnerArgspkg/integrations/github/ghrunner.go— addSetupRunner()usingpulumi-githubprovider withAppAuthpkg/integrations/github/api.go— refactor owner/repo parsing into shared helpercmd/mapt/cmd/params/params.go— add--ghactions-app-id,--ghactions-app-installation-id,--ghactions-app-private-keyflagsgithub.SetupRunner()before user-data generationgo.mod/go.sum— addgithub.com/pulumi/pulumi-github/sdk/v6 v6.14.0oci/Containerfile— installpulumi plugin resource github v6.14.0with renovate annotationdocs/self-hosted-runner.md— document all three auth options (App, PAT, manual token)Test plan
make build--ghactions-app-id/--ghactions-app-installation-id/--ghactions-app-private-keyGITHUB_TOKEN) still works--ghactions-runner-tokenpath still works🤖 Generated with Claude Code