How the Backstage GitHub Actions plugin shows workflow runs on entity pages
Platform teams usually want engineers to see build and deploy runs from the service page without switching to GitHub. The GitHub Actions plugin for Backstage is built for that. It reads workflow runs for the repository named in the entity's github.com/project-slug annotation and, depending on configuration, can re-run them. Treat it as a third-party plugin: before you install it, confirm its maintainer, package names and release activity against its own repository, because those details change and this page does not record them.
The decision that shapes the rest of the work is whether workflow actions run under each user's OAuth token or under a shared credential such as a GitHub App installation or a service token held by the portal. The answer changes who can see runs and who can trigger them. With per-user OAuth, GitHub's own repository permissions decide what each engineer sees and can re-run, which matches how access works in GitHub but means the plugin only shows data for users who have signed in with GitHub. With a shared credential, every Backstage user sees whatever the credential can read, so repositories that the portal's identity should not expose need to be excluded from the credential's scope before rollout.
Confirm three things before you choose. First, which repositories and organizations the plugin must cover, and whether any are private or restricted. Second, whether engineers should be able to re-run production deploy workflows from Backstage at all, or only view them. Third, how sign-in resolves GitHub identities to catalog users, since that mapping decides which user token is used. Write these answers into the design so the token type, the permission set and the annotation rules can be tested against real entities before the plugin is widely enabled.
What must be in place before the plugin is installed
The GitHub Actions plugin only works when the portal, the identity setup, the catalog data and the GitHub side agree. Work through these prerequisites first, because most failed installs trace back to a missing sign-in configuration, a credential with the wrong scope or a backend that cannot reach the GitHub API.
Running Backstage with GitHub sign-in
Backstage needs a working instance before any plugin is added, and the sign-in should use the built-in GitHub authentication provider. Configure a sign-in resolver so GitHub identities map to the catalog users your teams already use. The Backstage authentication documentation advises against offering guest access in production, so confirm guest sign-in is disabled before you connect the plugin. Users who sign in through GitHub are the ones whose tokens the plugin can use later.
GitHub App or OAuth App registration
Register either a GitHub App or an OAuth App for Backstage, and record which one you chose, because the token model and permission model differ. Confirm the scopes or permissions the chosen plugin documents, and grant only read access to Actions and the repositories that hold your components. For GitHub Enterprise Server, register the app on that instance rather than on github.com, and keep the client secret in your secrets store, not in configuration committed to source control.
Components with a known repository
The plugin finds workflow runs through an annotation on each catalog entity, so the component must point to a repository that exists in your GitHub organization. Audit the catalog for components with missing or stale repository URLs, and confirm each owner is a real group or user entity. Entities without a repository will show empty workflow tabs, which teams often report as a plugin fault when the actual gap is in catalog data.
Network path from the backend to GitHub
The plugin calls the GitHub API from the Backstage backend, not from the browser, so the backend host needs outbound HTTPS access to the API endpoint your organization uses. For GitHub Enterprise Server, this is the hostname of your own instance. Ask your network team to confirm egress rules, any proxy requirements and certificate trust for internal CAs before the install, because a blocked path usually appears as generic request errors in the UI.
Node.js version and Backstage version line
Choose the Backstage version line you will stay on before adding plugins, since plugin packages must match the core @backstage packages. The versioning policy supports two adjacent even-numbered Node.js releases, and as of Backstage 1.46.0 these are Node.js 22 and 24. Check that your build and runtime images use one of these supported versions, and check the plugin's release notes for the Backstage versions it targets.
User OAuth tokens or a shared credential for GitHub Actions
With user OAuth, each signed-in user's GitHub token drives the API calls that Backstage makes on their behalf. GitHub decides what that person can see and re-run, so the portal adds no permission layer of its own and inherits the repository model your organization already uses.
- Who can see runs: A user sees workflow runs only for repositories their GitHub account can read. An entity whose repository the user cannot access shows no runs to that user.
- Who can re-run: Re-run rights follow the user's repository role. A user with read access can see run history but cannot trigger a re-run.
- Audit trail: GitHub records re-runs against the individual account, so the audit record names the person. Confirm that Backstage logs also record the user identity.
- Token rotation: Tokens expire, are revoked when a user signs out or leaves the organization, and must be refreshed by the sign-in flow. Ask how the plugin handles lapsed sessions and what users see when a token stops working.
- Sign-in resolver interaction: The GitHub identity must resolve to the correct catalog user for the token to be attached to the right person. If a resolver maps several providers to one user, confirm which GitHub account the plugin uses.
Confirm with the plugin documentation that user tokens are supported in your setup and where it stores them.
A shared credential, such as a GitHub App installation or a service token, lets the backend read runs for every entity the credential covers. Visibility then depends on Backstage's catalog access controls rather than on each user's GitHub access, so the portal needs its own access model for this data.
- Who can see runs: Anyone who can open an entity page can see runs for every repository the credential reaches. Catalog and page-level access become the main boundary, so review which groups can reach those pages.
- Who can re-run: Re-run rights depend on the permissions granted to the credential. Confirm whether the plugin lets Backstage users trigger re-runs with it, and whether it restricts that action to particular roles.
- Audit trail: GitHub records actions under the app or service identity, so the individual requester does not appear unless Backstage records it. Plan logging inside Backstage to close that gap.
- Token rotation: A GitHub App issues installation tokens that expire, and its private key needs a separate rotation procedure. Confirm how the plugin refreshes installation tokens and where the key is stored.
- Sign-in resolver interaction: Sign-in does not decide which runs a user can see, so resolver errors affect audit attribution and catalog ownership instead. Keep the credential on the backend and out of the browser.
Check the plugin's documentation for the credential types it accepts before you plan a GitHub App around it.
The choice usually follows from two questions: who must be able to see runs, and whose identity must appear in the audit trail. Some plugin configurations support only one model, so confirm the supported credential types before you commit to an architecture.
- Visibility requirement: If GitHub repository access must govern who sees runs, user tokens fit that requirement. If every catalog reader may see runs for a defined set of repositories, a shared credential fits.
- Re-run controls: Decide whether shared viewers may re-run workflows at all. Test the behavior with a read-only account and with a repository maintainer account.
- Audit requirements: List the events that must name a person. A shared credential needs Backstage-side logging to meet that requirement.
- Credential support: Check which authentication types the plugin accepts, where it stores tokens, and whether its calls run in the backend or the frontend.
- Resolver design: Test each sign-in provider and confirm that the same person resolves to the same catalog user before you rely on user tokens.
Record the chosen model, the test results and the owner of the credential in the written scope before implementation begins.
Installing and configuring the GitHub Actions plugin in order
This sequence takes a Backstage instance from a plugin decision to a working view of GitHub Actions runs on one pilot entity, with re-runs limited to users who already have access to the repository. Each step ends with a check you can run before moving on.
Confirm the plugin maintainer and repository
Before installing anything, the platform team checks who publishes the GitHub Actions plugin, which repository it lives in, and whether its release activity and open issues look healthy for your Backstage version. Record the package names, the repository URL and the Backstage version you tested against in your change record. You are done when a reviewer has signed off on the plugin source and the version pin, and you know whether the plugin is in the community plugins repository or a vendor repository. Ask your Backstage integrator to confirm compatibility with your current release line before you proceed.
Add the frontend and backend packages
From the root of the Backstage app repository, the platform engineer runs the Backstage CLI to add the frontend and backend packages for the GitHub Actions plugin, so that versions stay aligned with the rest of the @backstage packages. Wire the frontend component into the entity page and register the backend plugin in the backend index file. You are done when
yarn installcompletes, the app builds locally, and the entity page renders the plugin tab without console errors.Register the GitHub credential outside the repository
Decide which credential model you use: a GitHub App installation, or a token tied to a service account. For user-level re-runs, each user signs in through GitHub OAuth so the request runs with their own permissions. Store client secrets and tokens in your secret manager or as environment variables injected at runtime, never in
app-config.yamlcommitted to Git. You are done when the backend starts with the credential loaded from the environment and a secret scan of the repository finds no GitHub token.Set the GitHub integration host configuration
In the app configuration, the platform engineer adds or confirms the GitHub integration entry for your host, including the host name and the reference to the credential from the previous step. This entry is shared with catalog discovery and other plugins, so changes here affect more than this plugin. You are done when the backend log shows the GitHub integration initialized for your host and a test call to the integration returns repository metadata for a known repository.
Annotate a pilot component
Choose one component in the software catalog whose repository has a working workflow and an owner who agrees to test. Add the
github.com/project-slugannotation to itscatalog-info.yamlwith the value inowner/repoform, then commit the change through the normal catalog review. You are done when the catalog shows the annotation on the entity after the next refresh and the entity page resolves the repository without an error.Restart the backend and confirm the pilot entity
The platform engineer restarts the Backstage backend so the new configuration and plugin registration take effect, then opens the pilot entity as a signed-in user. The plugin should list the latest workflow runs for the repository with status and links back to GitHub. You are done when the pilot entity shows its latest runs and the run links open the correct workflow on github.com.
Test re-run permissions for two users
Ask one user who has write access to the pilot repository to re-run a failed workflow from the entity page, then ask a second user who has no access to that repository to attempt the same action. The first re-run should succeed and appear in GitHub, and the second should be denied. You are done when both results match the repository permissions, and you have recorded the outcome in your test log before widening access to other teams.
Review the audit trail before wider rollout
Check the backend logs and the GitHub audit or workflow history to confirm each re-run is attributed to the signed-in user, not a shared account. Confirm the credential does not appear in frontend bundles or browser responses. You are done when the review is signed off by the security owner and the rollout plan lists which catalog components receive the annotation next.
Which Backstage fields map to which GitHub objects
This table pairs each Backstage object with its GitHub counterpart, the credential it needs and the permission it requires. Read it before you write the first annotation, because a mismatch at any row leaves the entity page empty or shows another team's runs. Rows marked as plugin-version dependent should be checked against the release your team installs.
| Backstage object | GitHub counterpart | Credential and permission | Version or setup note |
|---|---|---|---|
| github.com/project-slug annotation | Repository owner and name, written as owner/repo | Owner and repo must match the GitHub repository exactly, including case as GitHub displays it | Confirm the annotation key and format in the plugin README for your installed version |
| Catalog user entity | GitHub login, resolved by the sign-in resolver | Sign-in resolver must map each user to the same identity across providers | Resolver behavior depends on your auth provider configuration, not the plugin itself |
| Group ownership (spec.owner) | GitHub teams, only if your resolver or plugin reads team membership | Read access to organization membership, which usually needs an OAuth scope or app permission you grant | Whether team membership is used at all depends on the plugin version and resolver; confirm before relying on it |
| Workflow run identifiers | Run ID and workflow file name shown on the entity page | Actions read permission on the repository for viewing runs | Re-run actions need additional write-level Actions permission; confirm this per plugin release |
| User OAuth token | Acting GitHub user's permissions on each repository | Each viewer sees only runs their GitHub account can access; re-runs require that user to have write access | Check whether your installed plugin version supports per-user tokens for re-runs |
| Shared credential (GitHub App or PAT) | One identity performing all reads and re-runs | Scope is set once, but every visitor inherits its access and audit trail shows one actor | Use only where per-user access is not required, and limit it to the repositories listed in the catalog |
| Repositories not in the catalog | No Backstage entity to link runs to | Not reachable through entity pages | Add a catalog descriptor or accept that these runs stay in GitHub |
How to prove that the right people see the right runs
Test permissions with three named identities before the pilot opens to anyone else. Pick one user who has read access to the GitHub repository behind the pilot entity, one user who has no access to that repository, and one member of the team that owns the entity. Sign each one in to Backstage through the same provider the rest of the organization uses, then open the pilot entity's CI/CD tab. The user with access should see the workflow runs for the repository, the user without access should see nothing from it, and the owning team member should see the same runs as the first user. Record what each person sees, because a screenshot is weak evidence unless it is tied to a named account and a date.
Repeat the same three identities on each view the plugin exposes. Check the run list first, then open one run and confirm that the details match what the repository shows on GitHub. If the plugin displays job logs, test those separately, since log access can be more sensitive than run metadata. For the re-run control, confirm that the user with read-only access cannot trigger a re-run, and that a user who can re-run in GitHub can do so from Backstage only if your configuration intends that. Confirm what GitHub permission and token the re-run actually uses, since a shared credential can let a user act with more rights than their own account holds. Ask your plugin vendor or maintainer to document this behavior for your version.
Verify the sign-in resolver before trusting any of these results. Each GitHub identity must resolve to the catalog user your team expects, otherwise the permission checks test the wrong person. Confirm this by checking the signed-in user's identity in Backstage against the expected User entity in the catalog. Run the whole test with guest access turned off, because a guest session can hide identity mismatches and makes the results hard to attribute. Keep this test plan with your access review records so that a later change to the resolver or the plugin can be re-run against the same three identities.
Security settings for workflow visibility and re-runs
The GitHub Actions plugin reads workflow data and can trigger re-runs, so its credentials and sign-in settings carry real access. The cards below cover the controls that connect the plugin to Backstage's sign-in model and to GitHub's own permissions. Confirm each one against the plugin's security notes before production.
Keep tokens in backend configuration
Store GitHub tokens and GitHub App private keys in the backend secret configuration, loaded from your secret manager at runtime. Never place them in frontend code, in app-config values that ship to the browser, or in entity annotations, since anyone who can read the catalog can read annotations. Check the built frontend bundle and the catalog API output for stray credentials before go-live.
Scope GitHub permissions tightly
Grant the GitHub App or OAuth app read access to Actions data and only the write permission required for re-runs. Read-only visibility and re-run rights are separate decisions, so consider whether every user who can see workflow status also needs to trigger runs. Ask the security team to review the granted scopes against the plugin's documented requirements, and remove any broader permission left from testing.
Disable guest sign-in in production
Backstage's authentication guidance advises against offering guest access in production. Guest access would let an unauthenticated visitor reach the plugin's views and actions, and the re-run control inherits whatever identity the session holds. Confirm that the guest provider is absent from the production configuration, and test sign-in from a clean browser session after deployment.
Enforce a strict sign-in resolver
Configure sign-in resolvers so each provider maps to a catalog user that already exists, and reject identities that do not match. An unmatched GitHub account should fail sign-in rather than receive a default identity with inherited access. Make sure every provider resolves to the same identity model, so a user cannot gain a second, more permissive account through another login path.
Log re-run actions for review
Where your deployment supports audit logging, record which user triggered each re-run, the workflow, the repository and the time. Re-runs can repeat deployments or consume runner capacity, so the trail is what allows an investigation later. Confirm with the plugin and your Backstage version what the audit output contains, and send it to the same log store used for other portal events.
Rotate credentials on a set schedule
Agree a rotation interval with the security team and record the owner of each GitHub credential. Rotate the app private key or OAuth secret on that schedule, update the backend secret store, and restart the backend so the new value is loaded. Rotation also belongs in the response plan for any suspected leak, and each rotation should be tested in a non-production instance first.
Common GitHub Actions plugin failures and their fixes
This table lists the failures teams hit most often with the GitHub Actions plugin in Backstage, with the likely cause, the check that confirms it and the fix for each. Work through the rows by symptom: missing runs usually point to the annotation, partial visibility points to user tokens, and forbidden errors point to scopes. Check the annotation and token scope first, since most failures trace back to one of them.
| Symptom | Likely cause and check | Fix |
|---|---|---|
| Entity page shows no workflow runs | The github.com/project-slug annotation is missing, or it names the wrong owner or repository. Check the entity descriptor in the catalog for the exact owner/repo spelling and confirm the repository exists under that owner. | Add or correct the annotation so it reads owner/repository using the exact GitHub names, then refresh the entity in the catalog. |
| Runs appear for some users but not others | Each user's OAuth token lacks access to the repository, often because the user is outside the organization, has not granted the app access, or the org restricts OAuth apps. Compare the same entity while signed in as two users with different repository access. | Ask the affected user to sign in again and grant access, confirm the OAuth app is approved in the organization, or give the plugin a shared credential for read views if your policy allows it. |
| Re-run returns forbidden | The token used for the action lacks the write permission that re-running a workflow requires. Confirm the token scopes or fine-grained permissions in the GitHub settings for the signed-in user or the shared credential. | Grant the write-level Actions permission to the token that performs re-runs, or limit re-run buttons to users whose tokens carry that permission. |
| Plugin breaks after a Backstage upgrade | Package versions were bumped unevenly, so some @backstage packages and the GitHub Actions plugin packages no longer match. Run the version check in the repository and compare the installed package versions against the Backstage version. | Bump all @backstage packages together with yarn backstage-cli versions:bump, then update the GitHub Actions plugin packages to versions that match the new Backstage release. |
| Sign-in maps a GitHub user to the wrong catalog identity | The sign-in resolver matches on a claim that does not identify one person, or the GitHub username differs from the catalog user reference. Check the resolver output and the user entity that was linked. | Configure the resolver so the GitHub identity maps to one catalog user, and correct the user entity reference. Avoid guest access in production so unmapped users are not treated as signed in. |
| Re-run works for one owner but not another | The GitHub App or OAuth app is installed on only some organizations, so runs for repositories in the other organization cannot be read or triggered. List the organizations where the app is installed and compare them with the repository owners in your annotations. | Install or authorize the app in the missing organization, or move the annotation to a repository the app can already access. |
Questions buyers ask before setting up GitHub Actions in Backstage
How much effort does a GitHub Actions setup in Backstage take?
Effort depends on how many repositories and components need annotations, which credential model you choose, whether you run GitHub Enterprise Server, and how many sign-in and permission cases you need to test. A small catalog with one GitHub organization and a shared credential is a narrow job. A large catalog with several organizations, per-user sign-in and Enterprise Server adds annotation work, more sign-in cases and a longer test plan. No fixed duration applies to every environment, so ask for an effort estimate that lists each of these drivers separately in the written scope.
Can our own team set up the GitHub Actions plugin without a partner?
Yes, if your team already runs Backstage and has someone comfortable with its configuration and plugin packages. The work involves creating a GitHub App or OAuth application, configuring the plugin in the Backstage app, adding the github.com/project-slug annotation to components, and running a permission test plan. The main risk is not the installation itself but the testing: each user role, each repository visibility level and each sign-in path should be checked before teams rely on the view. A partner is most useful when that test plan is large or when no one on the team has owned Backstage plugin configuration before.
What does the work need from our side?
You need four things before work starts. First, a GitHub administrator who can create or approve a GitHub App or OAuth application and grant it access to the right organizations. Second, owners for each catalog component who can add the github.com/project-slug annotation or approve a change that adds it. Third, a named owner for the credential, who is responsible for rotating it, revoking it when someone leaves and reviewing its scope. Fourth, access to a non-production Backstage instance for testing. Ask the partner to confirm each of these in writing so that no step depends on an assumption.
Should we use user OAuth tokens or a shared credential for workflow re-runs?
Choose user OAuth when you need re-runs and views to reflect each person's own GitHub permissions, so that a user can only see or trigger what GitHub already allows them. Choose a shared credential when you want one service identity for read-only status views and accept that its permissions set the ceiling for everyone. User tokens add sign-in dependencies and per-user token handling. A shared credential is simpler to operate but needs tight scope and a clear owner. Many teams use a shared, read-only credential for status and restrict re-runs to user tokens. Decide this before building, because switching later changes the sign-in and test plan.
How do Backstage upgrades affect the GitHub Actions plugin?
Upgrades move all @backstage packages together, and the plugin's own packages need to stay compatible with that version. Backstage publishes a release line each month and a next line each week, and high and critical security fixes are backported to releases from the last six months where feasible. Plan to re-run the plugin's sign-in and re-run tests after each upgrade, and check the Backstage Upgrade Helper for template changes that touch your configuration. Confirm with the plugin maintainer which Backstage versions it supports before you choose a target version, and ask whether upgrade work is included in the scope or sold as a retainer.
Does GitHub Enterprise Server change the setup?
Yes. A GitHub Enterprise Server instance means the GitHub App or OAuth application, the callback URLs and the API base address all point to your own host rather than github.com. Certificates and network paths between Backstage and the server must work from the Backstage backend. Confirm the plugin's supported configuration for Enterprise Server with its documentation or maintainer, and include a connectivity and sign-in test for that host in the written scope.
What should we ask a partner to put in a written scope?
Ask for a list of GitHub organizations and repositories in scope, the credential model with a reason for the choice, the Backstage and plugin versions targeted, and the annotation work per component. Require a permission test plan that lists each user role, repository visibility level and sign-in path with expected results. Ask who owns the credential after handover, what runbook covers rotation and revocation, what happens if the GitHub App is removed, and whether upgrade support is included. Also ask which items are fixed and which depend on your catalog quality.
Who pays for ongoing maintenance after the plugin is live?
The plugin itself is open source, so recurring costs come from people and time rather than licenses. Your team or a partner covers credential rotation, reviewing access as people join and leave, annotation upkeep for new components, and testing after each Backstage upgrade. Ask the partner whether ongoing support is a separate retainer or a one-time handover, and what is documented so that your team can run the plugin without them. Costs recur mainly when the catalog grows or when Backstage upgrades change the plugin's configuration.
How DeployOpen works on this
DeployOpen treats the GitHub Actions integration as a scoped piece of work inside your Backstage deployment, not a plugin install. We agree on which entities, workflows and credential model are in scope, build and test the connection in your environment, and document it so your own team can operate it after handover.
How we scope
- Inventory the repositories and catalog entities that should show workflow runs, and which ones do not
- Decide between user OAuth tokens and a shared credential, with the access each option grants
- Agree in writing which re-run permissions are allowed, and for which roles and environments
- Confirm the GitHub organization, GitHub Enterprise Server details and Backstage version the work targets
How we build
- Add the plugin and the github.com/project-slug annotation to a pilot set of catalog entities
- Configure the sign-in resolver so user tokens map to the correct catalog identity
- Test that runs display correctly, that re-runs are authorized, and that tokens never reach the browser
- Keep all package versions aligned with the Backstage release line used for the deployment
How we hand over
- Provide configuration documentation for annotations, token handling and the permissions the integration needs
- Record the verification steps used during testing so your team can repeat them after changes
- Walk through the operating runbook for token rotation, plugin upgrades and troubleshooting failed runs
- Deliver the work with the scope, deliverables and acceptance criteria agreed before the build started
How we support
- Engagements are fixed-scope, with the scope and timeline agreed in writing before work begins
- Ongoing support, plugin upgrades and continuous testing are available as a retainer
- Ask any partner for a written quote that separates one-time setup from recurring support effort
- Confirm with GitHub and the plugin maintainers which permissions and features apply to your plan

