While reusable GitHub workflows do help with maintenance of GitHub Actions in general, reducing a lot of copy/paste from one repository to another, they still seem to have one big issue: dealing with secrets.
When implementing an action like "post to Slack", or "post to matrix/IRC", you will need some secrets for the bot account, and if you want to reuse this action in 50 repositories you can imagine while managing secrets in each repository does not scale.
I am looking for a solution to this problem that does not involve deploying secrets to all repositories using an action, some way to centralize them.
Keep in mind that reusable workflows work across organizations and I already have some of them shared across 4+ organizations. So configuring organization level secrets is not a solution either, also for other reasons: they can easily be exposed because they are available to any workflow (as opposed to environment based ones).
Check if the new (May 2022) keyword secrets: inherit
can help:
GitHub Actions: Simplify using secrets with reusable workflows
GitHub Actions simplifies using secrets with reusable workflows with the
secrets: inherit
keyword.Previously when passing secrets to a reusable workflow, you had to pass each secret as a separate argument.
Now you can simply pass the
secrets: inherit
to the reusable workflow and the secrets will be inherited from the calling workflow.
Learn more about reusable workflows in GitHub Actions and jobs.<job_id>.steps[*].uses
.
In the reusable workflow, reference the input or secret that you defined in the on key in the previous step.
If the secrets are inherited using
secrets: inherit
, you can reference them even if they are not defined in the on key.jobs: reusable_workflow_job: runs-on: ubuntu-latest environment: production steps: - uses: ./.github/workflows/my-action with: username: ${{ inputs.username }} token: ${{ secrets.envPAT }}
In the example above,
envPAT
is an environment secret that's been added to the production environment. This environment is therefore referenced within the job.Note: Environment secrets are encrypted strings that are stored in an environment that you've defined for a repository.
Environment secrets are only available to workflow jobs that reference the appropriate environment.
For more information, see "Using environments for deployment."
Again, see jobs.<job_id>.steps[*].uses
for additional examples.
As noted by wkhatch in the comments:
I don't believe this syntax is correct for using a reusable workflow, but is correct for using reusable actions.
You cannot call a reusable workflow as a step, but you can with an action.
As noted by Mickael V.'s comment, if you rely only on secrets: inherit
without further organization, you would indeed have to set the secrets individually in all calling repositories... which does not scale well.
However, you can centralize secrets while still benefiting from secrets: inherit
:
secrets-repo
) for managing reusable workflows.production
).secrets: inherit
, and specifying the central environment.As an example of a reusable workflow in a central repository (using here slackapi/slack-github-action
:
# .github/workflows/slack-notify.yml in central secrets-repo
name: Notify Slack
on:
workflow_call:
inputs:
message:
required: true
type: string
jobs:
notify_slack:
runs-on: ubuntu-latest
environment: production # centralized secrets environment
steps:
- name: Send Slack notification
uses: slackapi/[email protected]
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: ${{ inputs.message }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
You would call that workfrom from your other repositories (A, B, C, ...) like this:
jobs:
notify:
uses: my-org/secrets-repo/.github/workflows/slack-notify.yml@main
secrets: inherit # <===
environment: production # reference centralized secrets
with:
message: "Build successful!"
That way, you only define and manage secrets once, even if 50+ repos call the same reusable workflow.
As noted by wkhatch above, reusable workflows must be invoked at the job-level, whereas reusable actions are invoked at the step-level:
slack-notify.yml
) is called at the job-level. There are no steps
defined here, because you are calling the entire workflow, not a step. Reusable workflows are designed to be complete jobs (or sets of jobs) themselves, so they are invoked directly under jobs.slackapi/slack-github-action
is invoked within a step, which makes sense because it is a reusable action, not a workflow.This exact scenario is addressed in the GitHub roadmap issue GitHub Actions secrets improvements for Reusable workflows:
With this current improvement, teams managing reusable workflows can refer to the secrets from the called (source) repos. These secrets are available only in the reusable workflow run context within in the caller (target) repos.
Unfortunately, as of March 2024, the issue is scheduled for "Future"; there are columns up to Q4 2024.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With