GitHub Action - How to deploy release on multiple environment?

Viewed 7227

In my case, there are four environments, Dev, QA, UAT and Prod, windows based, self-hosted runners. Once the package is build, it should be deployed to each environment one after the another in a successful manner DevQAUATPROD. Below workflow has been written to build and deploy the package only for Dev environment. Now to deploy the release on QA, UAT and Prod environment further, should the same deployment section be repeated for QA, UAT and Prod. Is there no concept like classes where the steps of deploying the release can be called multiple times with arguments?

Workflow-API

Build section

name: PASH-API-Build-Deployment 
on: 
 push:
    branches: [dev]
    paths: 
    - "Pash.Web/**" 
jobs:
 build:
    runs-on: dev-build
    strategy:
      matrix:
        node-version: 3.1.301
    env:
      api-project:  "./Pash.Web/PASH.Api/PASH.Api.csproj"
      test-project:  "./Pash.Web/PASH.Api.Test/PASH.Api.Test.csproj"
      upload-artifacts-path: "./pashdotnetcorewebapp"
      artifact-package-zip-directory-path: "_PASH-API-CI/Pash-drop"
      
    steps:
    - name: Generate build number
      id: buildnumber
      uses: einaregilsson/build-number@v3 
      with:
        token: ${{ secrets.github_token }}
    - name: Print build number - env
      run: |
       echo "::set-output name=VAR-BUILD-NUMBER::${env:BUILD_NUMBER}"
       echo Build Id first way = ${env:BUILD_NUMBER}
       echo Build Id second way = ${{ steps.buildnumber.outputs.build_number }}
    
    - uses: actions/checkout@v2

    - name: Setup .NET Core - ${{ matrix.node-version }}
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: ${{ matrix.node-version }}

    - name: Install dependencies
      run: dotnet restore ${{env.api-project}}

    - name: Build
      run: dotnet build ${{env.api-project}} --configuration Release --no-restore

    - name: Test
      run: dotnet test ${{env.test-project}} --no-restore --verbosity normal

    - name: Publish
      run: dotnet publish ${{env.api-project}} -c Release -o pashdotnetcorewebapp

    - name: publish artifacts
      uses: actions/upload-artifact@v2
      with:
       name: pash-api-artifact-${{ steps.buildnumber.outputs.build_number }}
       path: ${{ env.upload-artifacts-path }}

    - name: Store Build Number on Build Server 
      run: echo ${{ steps.buildnumber.outputs.build_number }} > ${{github.workspace}}/buildnumberapi.txt
    
    - name: Publish Upload Build File 
      uses: actions/upload-artifact@v2
      with:
        name: buildnumberapi
        path: ${{github.workspace}}/buildnumberapi.txt

Deploy section

  deploy:
    needs: [build]
    runs-on: dev-deploy

    env:
      deploy-powershell-script:  "D:\\github-deploy-ps.ps1"
      stop-powershell-script:  "D:\\stop-website-ps.ps1"
      pool-name: "PASHAPIPool"
      site-name: "PASHServicesAPISite"

    steps:
    #- name: Print Build Number from BUILD job
      #run: echo ${{ needs.build.output.VAR-BUILD-NUMBER}}

    - name: Download Build File
      uses: actions/download-artifact@v2
      with:
        name: buildnumberapi
        path: ${{github.workspace}}

    - name: Print build ID
      run: |
        $varbuildnumber = cat ${{github.workspace}}/buildnumberapi.txt
        echo The result is $varbuildnumber
        echo "::set-output name=var-build-number::$varbuildnumber"
      id: selectbuildID

    - name: Download Release Artifacts
      uses: actions/download-artifact@v2
      with:
        name: pash-api-artifact-${{steps.selectbuildID.outputs.var-build-number}}
        path: ${{github.workspace}}/${{ env.artifact-package-zip-directory-path }}
 
    - name: Run Powershell commands to deploy release
      run: |
        & '${{env.deploy-powershell-script}}' ${{env.pool-name}} ${{env.site-name}} ${{env.physical-path}} ${{ env.port-name}} 

Now the question is, should the same deployment section be repeated again in the same workflow for QA, UAT and Prod. This does not seem a good choice? I am new to GitHub Actions and your suggestions would be very helpful.

2 Answers

There is such concept and it is called composite action

All what you need is to create a file with parameterized steps.

For instance octocat/say-hello/action.yml:

inputs:
  name: 
    description: 'Your name'
    default: 'No name provided'
runs:
  using: "composite"
  steps: 
    - run: echo Hello ${{ inputs.name }}.
      shell: bash
    - run: echo "Nice to meet you!"
      shell: pwsh

And then use in your workflow:

jobs:
  build:
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v2
    - uses: octocat/say-hello@v1
      with: 
        name: OctoCat

Your envs should be available. Please check this:

  • composite action
inputs:
  name: 
    description: 'Your name'
    default: 'No name provided'
  upload-artifacts-path: 
    description: 'Path'
    default: "some/path"
runs:
  using: "composite"
  steps: 
    - run: echo Hello ${{ inputs.name }}.
      shell: bash
    - run: echo "Nice to meet you!"
      shell: bash
    - run: echo "$deploy_powershell_script"
      shell: bash
    - run: echo "$stop_powershell_script"
      shell: bash
    - run: echo "${{ inputs.upload-artifacts-path }}"
      shell: bash
    
  • workflow file
name: composite
on:
  workflow_dispatch:

env:
  deploy_powershell_script:  "D:\\github-deploy-ps.ps1"


jobs:
  build:
    runs-on: windows-latest

    env:
      stop_powershell_script:  "D:\\stop-website-ps.ps1"
      upload_artifacts_path: "./pashdotnetcorewebapp"
      
    steps:
    - uses: actions/checkout@v2
    - uses: ./.github/actions/say-hello
      with: 
        name: OctoCat
        upload-artifacts-path: "$upload_artifacts_path"
    - run: echo "$deploy_powershell_script"
      shell: pwsh
    - run: echo "$upload_artifacts_path"
      shell: pwsh
    - name: Dump steps context
      env:
        STEPS_CONTEXT: ${{ toJson(steps) }}
      run: echo "$STEPS_CONTEXT"
  • log
Run ./.github/actions/say-hello
  with:
    name: OctoCat
    upload-artifacts-path: $upload_artifacts_path
  env:
    deploy_powershell_script: D:\github-deploy-ps.ps1
    stop_powershell_script: D:\stop-website-ps.ps1
    upload_artifacts_path: ./pashdotnetcorewebapp
Hello OctoCat.
Nice to meet you!
D:\github-deploy-ps.ps1
D:\stop-website-ps.ps1
./pashdotnetcorewebapp

I tested here few aspects of accessing variables and env variables defined at job level are available in composite action.

But if you want to have inputs defined as env variables you need to map them separately for each step.

Related