In this lesson, you’ll learn how to securely pass secrets into a reusable GitHub Actions workflow. We’ll cover:
Inspecting a reusable workflow to identify required secrets
Two approaches for passing secrets
A step-by-step guide to explicitly declare and pass secrets
Common pitfalls and how to propagate environment variables
Inspecting the Reusable Workflow
First, review the reusable workflow metadata to see which secrets it expects:
name : Deployment - Reusable Workflow
on :
workflow_call :
jobs :
reuse-deploy :
environment :
name : development
url : http://example.com
outputs :
APP_INGRESS_URL :
runs-on : ubuntu-latest
steps :
- name : Checkout Repo
uses : actions/checkout@v4
- name : Install kubectl CLI
uses : azure/setup-kubectl@v3
with :
version : '1.26.0'
- name : Set Kubeconfig file
uses : azure/k8s-set-context@v3
with :
# ...
A quick search shows this workflow requires two secrets:
Secret Name Purpose k8s-kubeconfigKubernetes cluster credentials mongodb-passwordMongoDB database password
These must be supplied by the caller workflow (the “Solar System Workflow”).
Caller Workflow Example
Here’s how you might create a Kubernetes secret and deploy in your caller workflow:
- name : Create MongoDB Secret
run : |
kubectl -n ${{ vars.NAMESPACE }} create secret generic mongo-db-creds \
--from-literal=MONGO_URI=${{ env.MONGO_URI }} \
--from-literal=MONGO_USERNAME=${{ vars.MONGO_USERNAME }} \
--from-literal=MONGO_PASSWORD=${{ secrets.MONGO_PASSWORD }} \
--save-config -o yaml | kubectl apply -f -
- name : Deploy to Dev Env
run : |
kubectl apply -f kubernetes/development
- name : Set App Ingress Host URL
id : set-ingress-host-address
run : |
echo "APP_INGRESS_HOST=$(kubectl -n ${{ vars.NAMESPACE }} \
get ingress -o jsonpath='{.items[0].spec.tls[0].hosts[0]}')"
Approaches to Passing Secrets
You have two main methods for forwarding secrets to a reusable workflow:
Method Description secrets: inheritAutomatically inherits all organization-level secrets. Explicit secrets declaration You specify exactly which secrets to forward, improving clarity and security.
Using secrets: inherit is quick, but explicit declaration reduces blast radius by only passing the secrets you need.
Step-by-Step: Explicitly Passing Secrets
Follow these steps to declare and forward secrets in your reusable workflow.
1. Declare Secrets in the Reusable Workflow
Add a secrets section under workflow_call:
name : Deployment - Reusable Workflow
on :
workflow_call :
secrets :
k8s-kubeconfig :
required : true
mongodb-password :
required : true
jobs :
reuse-deploy :
environment :
name : development
url : https://${{ steps.set-ingress-host-address.outputs.APP_INGRESS_HOST }}
outputs :
APP_INGRESS_HOST : ${{ steps.set-ingress-host-address.outputs.APP_INGRESS_HOST }}
runs-on : ubuntu-latest
steps :
- name : Checkout Repo
uses : actions/checkout@v4
- name : Install kubectl CLI
uses : azure/setup-kubectl@v3
with :
version : '1.26.0'
- name : Set Kubeconfig file
uses : azure/k8s-set-context@v3
with :
kubeconfig : ${{ secrets.k8s-kubeconfig }}
- name : Create MongoDB Secret
run : |
kubectl -n ${{ vars.NAMESPACE }} create secret generic mongo-db-creds \
--from-literal=MONGO_URI=${{ env.MONGO_URI }} \
--from-literal=MONGO_USERNAME=${{ vars.MONGO_USERNAME }} \
--from-literal=MONGO_PASSWORD=${{ secrets.mongodb-password }} \
--save-config -o yaml | kubectl apply -f -
- name : Deploy to Dev Env
run : kubectl apply -f kubernetes/development
- name : Set App Ingress Host URL
id : set-ingress-host-address
run : |
echo "APP_INGRESS_HOST=$(kubectl -n ${{ vars.NAMESPACE }} \
get ingress -o jsonpath='{.items[0].spec.tls[0].hosts[0]}')"
2. Call the Reusable Workflow with Secrets
Reference the reusable workflow from your Solar System repo and pass the required secrets:
jobs :
dev-deploy :
if : contains(github.ref, 'feature/')
needs : docker
uses : ./.github/workflows/reuse-deployment.yml
secrets :
k8s-kubeconfig : ${{ secrets.KUBECONFIG }}
mongodb-password : ${{ secrets.MONGO_PASSWORD }}
If a required secret is missing, the workflow will fail to start with an “invalid workflow file” error. Always verify secret names and availability before committing.
Successful execution will show:
Limitation: Environment Variables Aren’t Propagated
Note that environment variables (e.g., MONGO_URI) defined in the caller do not automatically flow into a reusable workflow:
echo $URL
curl https:// $URL /live -s -k | jq -r .status | grep -i live
# Error: exit code 1
In the Create MongoDB Secret logs, you’ll see an empty URI:
kubectl -n development create secret generic mongo-db-creds \
--from-literal=MONGO_URI= \
--from-literal=MONGO_USERNAME=superuser \
--from-literal=MONGO_PASSWORD= *** \
--save-config -o yaml | kubectl apply -f -
env:
MONGO_URI:
MONGO_USERNAME: superuser
MONGO_PASSWORD: ***
We’ll cover strategies to propagate environment variables across workflows in the next lesson.
Solar System Workflow (Caller)
Below is a complete example of your Solar System Workflow, showing how to set environment variables and call the reusable deployment workflow:
name : Solar System Workflow
on :
workflow_dispatch :
push :
branches :
- main
- 'feature/*'
env :
MONGO_URI : 'mongodb+srv://supercluster.d83jj.mongodb.net/superData'
MONGO_USERNAME : ${{ vars.MONGO_USERNAME }}
MONGO_PASSWORD : ${{ secrets.MONGO_PASSWORD }}
jobs :
unit-testing :
# ...
code-coverage :
# ...
docker :
# ...
dev-deploy :
if : contains(github.ref, 'feature/')
needs : docker
uses : ./.github/workflows/reuse-deployment.yml
secrets :
k8s-kubeconfig : ${{ secrets.KUBECONFIG }}
mongodb-password : ${{ secrets.MONGO_PASSWORD }}
# ... other jobs
Links and References