okaryo.log

Building a Job Using Different Secrets per Environment in a Single GitHub Actions Workflow File | okaryo.log

Building a Job Using Different Secrets per Environment in a Single GitHub Actions Workflow File

    #GitHubActions#GitHub#CI/CD

Introduction

When setting up workflows in GitHub Actions, there are cases where you want to create workflows for both the production and staging environments, but the only difference is the secret values, while the workflow content remains the same.

To make the workflow more efficient and reusable, I needed to use something I hadn’t tried before: reusable workflows. Here’s a record of how I implemented it.

Method

As an example, let’s say you have a workflow for deploying to both the production and staging environments, where the deployment process is the same, but the destination is controlled by the secret values. The keys for each secret are as follows:

  • Production environment: secrets.DEPLOY_KEY_PRODUCTION
  • Staging environment: secrets.DEPLOY_KEY_STAGING

If you were to naively construct this workflow, the following patterns could emerge:

  • Use if statements within the same workflow file to switch secrets
  • Create separate workflow files like deploy-production.yml and deploy-staging.yml for each environment

Both methods can work, but the former increases the number of lines, making the control logic more complex and harder to read. The latter increases the number of duplicated files, making changes and management more cumbersome.

To address these issues, I wanted to use the same workflow while allowing different secrets to be used under the same key. This can be achieved using reusable workflows, which allow you to share common processes across multiple workflows.

First, I create the usual workflow, triggered by a push to either the main or develop branches.

name: Deploy

on:
  push:
    branches:
      - main
      - develop

jobs:
  staging:
    if: github.ref == 'refs/heads/develop'
    uses: ./.github/workflows/_deploy.yml
    with:
      environment: staging
    secrets:
      DEPLOY_KEY: ${{ secrets.DEPLOY_KEY_STAGING }}

  production:
    if: github.ref == 'refs/heads/main'
    uses: ./.github/workflows/_deploy.yml
    with:
      environment: production
    secrets:
      DEPLOY_KEY: ${{ secrets.DEPLOY_KEY_PRODUCTION }}

Here, I call the jobs for the staging and production environments, controlling them with if statements. The staging job is triggered when a push is made to the develop branch, and the production job is triggered when a push is made to the main branch. Then, using uses: ./.github/workflows/_deploy.yml, I call the reusable workflow. At this point, I pass the variables and secrets to be used for each environment using with and secrets.

The _deploy.yml is configured as follows:

name: _Deploy

on:
  workflow_call:
    inputs:
      environment:
        type: string
        description: Name of target environment
        required: true
    secrets:
      DEPLOY_KEY:
        description: Deploy key
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      run: |
        echo ${{ inputs.environment }}
        echo ${{ secrets.DEPLOY_KEY }}

In the workflow_call, I set the trigger to allow the workflow to be called from another workflow. I also define the variables and secrets passed from the workflow using inputs and secrets.

With this setup, I can now use the separate secrets DEPLOY_KEY_PRODUCTION and DEPLOY_KEY_STAGING as DEPLOY_KEY within the same workflow.

Conclusion

At first, I tried to use outputs to absorb the differences in secrets for each environment and standardize the workflow. However, I found that secrets couldn’t be passed to the workflow, and even if I tried, it would have required encryption and decryption, which would have made the process overly complicated.

I realized that I still need more experience with GitHub Actions.


Related Posts
Related Posts
Promotion

This site uses Google Analytics.