GitHub Actions Certification
Reusable Workflows and Reporting
Step 4 Using Outputs in Reusable Workflow
In this lesson, we’ll walk through exposing outputs from a reusable workflow so downstream jobs—in this case, dev-integration-testing—can access the application URL generated during deployment.
Troubleshooting the Integration Test Failure
When dev-integration-testing runs without the exposed URL, you might see:
echo $URL
# shell: /usr/bin/bash -e {0}
# env:
# MONGO_URI: mongodb+srv://...
URL: [
Error: Process completed with exit code 1.
The root cause is that APP_INGRESS_URL
isn’t available to the test job. To fix this, we need to define and export outputs
in our reusable workflow.
1. Define Workflow-Level Outputs
Edit .github/workflows/reuse-deployment.yml
and add an outputs
section under on.workflow_call
:
name: Deployment - Reusable Workflow
on:
workflow_call:
inputs:
environment:
description: Deployment environment (dev or prod)
required: true
default: dev
type: string
mongodb-uri:
description: MongoDB connection URI
required: true
type: string
k8s-manifest-dir:
description: Path to Kubernetes manifests
required: true
type: string
kubectl-version:
description: kubectl version
required: false
default: v1.24.0
type: string
secrets:
k8s-kubeconfig:
required: true
mongodb-password:
required: true
outputs:
application-url:
description: The application ingress URL
value: ${{ jobs.reuse-deploy.outputs.APP_INGRESS_URL }}
2. Map Job Outputs to Workflow Outputs
Inside the reuse-deploy
job, expose the ingress host address:
jobs:
reuse-deploy:
runs-on: ubuntu-latest
environment:
name: ${{ inputs.environment }}
url: https://${{ steps.set-ingress-host.outputs.ingress_host }}
outputs:
APP_INGRESS_URL: ${{ steps.set-ingress-host.outputs.ingress_host }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install kubectl
uses: azure/setup-kubectl@v3
with:
version: ${{ inputs.kubectl-version }}
- name: Configure kubeconfig
uses: azure/k8s-set-context@v3
with:
kubeconfig: ${{ secrets.k8s-kubeconfig }}
- name: Deploy manifests
run: |
kubectl apply -f ${{ inputs.k8s-manifest-dir }}
echo "Deployment complete."
- name: Extract ingress host
id: set-ingress-host
run: |
host=$(kubectl get ingress \
-n ${{ inputs.environment }} \
-o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "ingress_host=$host" >> $GITHUB_OUTPUT
Note
Make sure the id
in the step (here: set-ingress-host
) matches when you reference steps.<id>.outputs
.
3. Consume Outputs in the Caller Workflow
In your main workflow (e.g., .github/workflows/ci.yml
), invoke the reusable workflow and pass its outputs to integration tests:
jobs:
docker:
runs-on: ubuntu-latest
# Build and push image
steps: …
dev-deploy:
needs: docker
uses: ./.github/workflows/reuse-deployment.yml
with:
mongodb-uri: ${{ vars.MONGO_URI }}
environment: development
k8s-manifest-dir: kubernetes/development
secrets:
k8s-kubeconfig: ${{ secrets.KUBECONFIG }}
mongodb-password: ${{ secrets.MONGO_PASSWORD }}
dev-integration-testing:
needs: dev-deploy
runs-on: ubuntu-latest
steps:
- name: Run integration tests
env:
URL: ${{ needs.dev-deploy.outputs.application-url }}
run: |
echo "Testing $URL"
curl -s -k https://$URL/live | jq -r '.status' | grep -qi live
prod-deploy:
if: github.ref == 'refs/heads/main'
needs: docker
uses: ./.github/workflows/reuse-deployment.yml
with:
mongodb-uri: ${{ vars.MONGO_URI }}
environment: production
k8s-manifest-dir: kubernetes/production
secrets:
k8s-kubeconfig: ${{ secrets.KUBECONFIG }}
mongodb-password: ${{ secrets.MONGO_PASSWORD }}
prod-integration-testing:
if: github.ref == 'refs/heads/main'
needs: prod-deploy
runs-on: ubuntu-latest
steps:
- name: Validate production URL
env:
URL: ${{ needs.prod-deploy.outputs.application-url }}
run: |
echo "Production URL: $URL"
curl -s -k https://$URL/live | jq -r '.status' | grep -qi live
Job | Consumes Output |
---|---|
dev-deploy | Generates application-url via reusable wf |
dev-integration-testing | Uses ${{ needs.dev-deploy.outputs.application-url }} |
prod-deploy | Generates application-url for production |
prod-integration-testing | Uses ${{ needs.prod-deploy.outputs.application-url }} |
4. Verify the Workflow Summary
After committing and pushing, the GitHub Actions summary will show all jobs passing, including the integration tests with the correct URLs.
A snippet from dev-integration-testing logs confirms the URL is passed correctly:
# env: URL: solar-system-development.172.232.87.200.nip.io
# Testing solar-system-development.172.232.87.200.nip.io
curl -s -k https://solar-system-development.172.232.87.200.nip.io/live | jq -r '.status'…
With this setup, your workflows remain modular, DRY, and easy to manage by:
- Defining inputs, secrets, and outputs in a reusable workflow.
- Mapping job-level outputs to workflow-level outputs.
- Accessing those outputs in downstream jobs.
Links and References
Watch Video
Watch video content