GitHub Actions

Continuous Deployment with GitHub Actions

Setting Output for Integration testing

Extend your GitHub Actions workflow with an integration test that automatically picks up your application’s dynamic Ingress host URL. This guide shows you how to:

  • Deploy manifests to a Kubernetes cluster
  • Capture the Ingress hostname as a workflow output
  • Consume that output in a downstream integration-testing job

Adding the Integration Test Job

After your dev-deploy job completes, add an integration-testing job that references the URL output:

jobs:
  integration-testing:
    name: Dev Integration Testing
    needs: [dev-deploy]
    runs-on: ubuntu-latest
    steps:
      - name: Test URL Output with curl and jq
        env:
          URL: ${{ needs.dev-deploy.outputs.APP_INGRESS_URL }}
        run: |
          echo "URL: $URL"
          echo "-----------------------------------------"
          curl https://$URL/live -s -k | jq -r .status | grep -i live

Note

The curl and jq utilities are pre-installed on the ubuntu-latest runner.

Warning

Using curl -k skips TLS verification. Only use this in non-production or trusted test environments.

Retrieving the Ingress Host URL

To surface the Ingress host from Kubernetes into your workflow:

  1. Invoke kubectl in the deploy job to read the host via JSONPath.
  2. Write that hostname to GITHUB_OUTPUT.
  3. Expose it as a job-level output.

1. Modify the Deploy Job

In your dev-deploy job, after applying the manifests, add a step with an ID to capture the host:

jobs:
  dev-deploy:
    needs: docker
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Install kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: '1.26.0'

      - name: Configure Kubeconfig
        uses: azure/k8s-set-context@v3
        with:
          method: kubeconfig
          kubeconfig: ${{ secrets.KUBECONFIG }}

      - name: Deploy to Development
        run: kubectl apply -f kubernetes/development

      - id: set-ingress-host
        name: Set App Ingress Host URL
        run: |
          echo "APP_INGRESS_HOST=$(kubectl -n ${{ vars.NAMESPACE }} \
            get ingress -o jsonpath='{.items[0].spec.tls[0].hosts[0]}')" \
            >> "$GITHUB_OUTPUT"

Kubernetes Ingress Example

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: solar-system
  namespace: development
spec:
  rules:
    - host: solar-system-{{ .Namespace }}.{{ .Ingress.IP }}.nip.io
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: solar-system
                port:
                  number: 3000
  tls:
    - hosts:
        - solar-system-{{ .Namespace }}.{{ .Ingress.IP }}.nip.io
      secretName: solar-system

2. Extract the Ingress Host via CLI

Run these commands locally or in a step to confirm your JSONPath:

CommandDescription
kubectl -n development get ingressList all ingresses in the development namespace
kubectl -n development get ingress -o jsonpath='{.items[0].spec.tls[0].hosts[0]}'Extract the first TLS host from the ingress
kubectl -n development get ingress
# OUTPUT:
# NAME           HOSTS                                           ADDRESS                       PORTS   AGE
# Extract only the host:
kubectl -n development get ingress \
  -o jsonpath='{.items[0].spec.tls[0].hosts[0]}'
# solar-system-development.172.232.87.200.nip.io

3. Expose the Step Output as a Job Output

Enable downstream jobs to consume the captured host by defining an outputs section:

jobs:
  dev-deploy:
    needs: docker
    runs-on: ubuntu-latest
    outputs:
      APP_INGRESS_URL: ${{ steps.set-ingress-host.outputs.APP_INGRESS_HOST }}
    steps:
      # ... (previous steps) ...

Consuming the Output in Integration Testing

In the integration-testing job, map the job output to an environment variable:

jobs:
  integration-testing:
    name: Dev Integration Testing
    needs: dev-deploy
    runs-on: ubuntu-latest
    steps:
      - name: Test URL Output with curl and jq
        env:
          URL: ${{ needs.dev-deploy.outputs.APP_INGRESS_URL }}
        run: |
          echo "URL: $URL"
          echo "-----------------------------------------"
          curl https://$URL/live -s -k | jq -r .status | grep -i live

Passing Values Between Jobs

The image shows a GitHub Docs page about passing values between steps and jobs in a workflow, with navigation links and support options.

Learn more in the GitHub Actions docs on passing values between jobs.

Official Example

jobs:
  job1:
    runs-on: ubuntu-latest
    outputs:
      output1: ${{ steps.step1.outputs.test }}
      output2: ${{ steps.step2.outputs.test }}
    steps:
      - id: step1
        run: echo "test=hello" >> "$GITHUB_OUTPUT"
      - id: step2
        run: echo "test=world" >> "$GITHUB_OUTPUT"

  job2:
    runs-on: ubuntu-latest
    needs: job1
    steps:
      - env:
          OUTPUT1: ${{ needs.job1.outputs.output1 }}
          OUTPUT2: ${{ needs.job1.outputs.output2 }}
        run: echo "$OUTPUT1 $OUTPUT2"

Workflow Run Summary

The image shows a GitHub Actions workflow summary for a project named "solar-system," indicating a successful run with various jobs like unit testing, code coverage, and containerization. The workflow was triggered by a push and completed in 2 minutes and 4 seconds.

Integration Testing Job Log

The image shows a GitHub Actions workflow interface with a successful "Dev Integration Testing" job, displaying job setup and test output details.

This confirms that the dynamic Ingress host URL was successfully passed from the deploy job to the integration-testing job.

References

Watch Video

Watch video content

Previous
Workflow Create Secret and Deploy to Kubernetes Dev Environment