Working on Github actions for the first time.
In my .yml file I have the following
on:
workflow_dispatch:
branches:
- main
inputs:
environment:
type: choice
description: 'Select environment to deploy in'
required: true
options:
- dev
- non-prod
- prod
- staging
based on the option I need to do the following
for staging
- name: build
run: CI=false yarn build-staging
for non-prod
- name: build
run: CI=false yarn build
Could you please provide me with some pointers on how this can be achieved?
The simplest way to go about it would be to use an if condition on the jobs within your workflow, for example:
on:
workflow_dispatch:
branches:
- main
inputs:
environment:
type: choice
description: 'Select environment to deploy in'
required: true
options:
- dev
- non-prod
- prod
- staging
jobs:
staging:
runs-on: ubuntu-latest
if: inputs.environment == 'staging'
steps:
- name: build
run: CI=false yarn build-staging
prod:
runs-on: ubuntu-latest
if: inputs.environment == 'prod'
steps:
- name: build
run: CI=false yarn build
Related
I would like to trigger a github action wf for a specific branch.
My branch has the name
refs/heads/release/rc22-15.0.0
I would like to trigger the wf or a specific step for all releases refs/heads/release/**
The execution of the wf triggers both steps.
name: wf_logic_test_releasebranch
on:
workflow_dispatch:
push:
branches:
- 'release/**'
- 'feature/**'
- 'main'
jobs:
test_condition:
name: job_test_condition
runs-on: [atc-ubuntu-20.04]
environment: sandbox
steps:
- name: Branch name
if: github.ref == 'refs/heads/release/rc22-15.0.0'
run: echo running on branch ${GITHUB_REF##*/}
- run: echo ${{github.ref}}
By changing the code to:
name: wf_logic_test_releasebranch
on:
workflow_dispatch:
push:
branches:
- 'release/**'
- 'feature/**'
- 'main'
jobs:
test_condition:
name: job_test_condition
runs-on: [atc-ubuntu-20.04]
environment: sandbox
steps:
- name: Branch name
if: github.ref == 'refs/heads/release/**'
run: echo running on branch ${GITHUB_REF##*/}
- run: echo ${{github.ref}}
The execution of the above wf triggers only the second step.
This is what worked for me:
name: wf_logic_test_releasebranch
on:
workflow_dispatch:
push:
branches:
- 'release/**'
- 'feature/**'
- 'main'
jobs:
test_condition:
name: job_test_condition
runs-on: [atc-ubuntu-20.04]
environment: sandbox
steps:
- name: Always call branch name
run: echo running on branch ${GITHUB_REF##*/}
#WF executes step only if branch name is main
- name: Determine IP of runner only for release branch
if:
contains(github.ref, 'release')
run: curl https://api.ipify.org
- name: Show branch name for main and feature branch only
if:
contains(github.ref, 'main') || contains(github.ref, 'feature')
run: echo running on branch ${GITHUB_REF##*/}
job_only_for_main:
name: job_test_only_for_main
runs-on: [atc-ubuntu-20.04]
environment: sandbox
if:
contains(github.ref, 'main')
steps:
- name: Always call branch name
run: echo running on branch ${GITHUB_REF##*/}
I am using a reusable workflow, and the calling workflow does not report a failure if the reused workflow fails.
If I were to call the workflow directly, a failure would occur and get reported which is the expected behaviour.
What needs to be done to be able to report a failure in the workflow?
Calling Workflow
name: Deploy to dev
on:
push:
branches:
- 'main'
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
call-workflow-passing-data:
uses: ./.github/workflows/deploy-to-env.yml
with:
environment: dev
secrets: inherit
continue-on-error: false
Reused Workflow
name: Deploy to Environment
on:
workflow_call:
inputs:
environment:
required: true
type: string
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
validate:
runs-on:
- my-custom-runner
name: Apply Terraform
environment:
name: ${{ inputs.environment }}
env:
TF_VAR_environment: dev
steps:
- name: Checkout this repo
uses: actions/checkout#v3
- uses: actions/setup-node#v3
with:
node-version: 14
- uses: hashicorp/setup-terraform#v2
with:
terraform_version: 1.2.3
- name: Terraform fmt
id: fmt
run: terraform fmt -check
continue-on-error: false
- name: Terraform Init
id: init
run: terraform -chdir=terraform/src init
- name: Terraform Plan
id: plan
run: terraform plan
continue-on-error: false
- name: Terraform Apply
id: apply
run: terraform apply
continue-on-error: false
- name: Terraform outputs
id: outputs
run: terraform output -json
continue-on-error: true
I am trying to deploy infrastructure as code from main branch on multiple environments with GitHub environments. I want to deploy whenever there is merge/push to main in development env, but when there is a tag on the commit like r2022-09-07 deploy the code on a staging env. but it fails every time due to the protection rule.
This is the error I get when the code needs to be deployed on staging:
This is the ci.yml workflow I have for deploying on multiple env from main branch using GitHub env.
name: Lint, Compile and Deploy
on:
push:
branches: [main]
tags:
- 'r*'
pull_request:
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
- name: install deps
run: yarn --frozen-lockfile
- run: yarn lint
- run: yarn prettier
- run: yarn compile
- run: yarn synth
- run: yarn test
# CD: ci -> dev -> staging -> production
## only deploy to dev from main branch
deploy-dev:
if: ${{ github.ref_name == 'main' }}
needs: ci
runs-on: ubuntu-latest
environment:
name: Dev
url: https://...
env:
STACK: ...
AAD_TENANT: ...
ARM_TENANT_ID: ...
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
steps:
- uses: actions/checkout#v3
- run: yarn --frozen-lockfile --production
- run: |
az login --service-principal --tenant $AAD_TENANT \
--username "${{ secrets.AZURE_CLIENT_ID }}" --password "${{ secrets.AZURE_CLIENT_SECRET }}"
yarn deploy $STACK --auto-approve
## deploy to staging only from main branch, if a commit has a tag starting with `r` (for ex. r2022-09-07)
deploy-staging:
if: ${{ startsWith(github.ref, 'refs/tags/r') }}
runs-on: ubuntu-latest
environment:
name: Staging
URL: ....
env:
STACK: ...
AAD_TENANT: ...
ARM_TENANT_ID: ...
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
steps:
- uses: actions/checkout#v3
- run: yarn --frozen-lockfile --production
- run: |
az login --service-principal --tenant $AAD_TENANT \
--username "${{ secrets.AZURE_CLIENT_ID }}" --password "${{ secrets.AZURE_CLIENT_SECRET }}"
yarn deploy $STACK --auto-approve
Staging env protection rules configs:
I was following the official GitHub docs but didn't find anything specific for this case, any idea what should be fixed in the above yaml?
Based on your last screenshot, push events on the main branch are going to be permitted to use the Staging environment.
I've been playing around with Environments too and had my own question, which lead me to yours!
My suggestion would be to remove branch protections and then use workflow logic to call the specific Environment:
on:
push:
branches: [main]
tags:
- 'r*'
pull_request:
jobs:
ci:
if: startsWith(github.ref_name, 'r*') || github.ref_name == 'main'
runs-on: ubuntu-latest
environment: Staging
steps:
...
Edit based on comments made by OP on 10/12/2022
If you want to deploy to dev when you only push to main:
on:
push:
branches: [main]
jobs:
ci-dev-only:
if: github.ref_name == main
runs-on: ubuntu-latest
environment: dev
steps:
...
ci-staging:
if: github.ref_type == tag
runs-on: ubuntu-latest
environment: staging
steps:
...
ci-prod:
if: github.ref_type == tag && startsWith(github.ref_name, 'r*')
runs-on: ubuntu-latest
environment: prod
steps:
...
Keep in mind that tags are branch agnostic. You can't pin them on a branch.
That all being said, I think releasing to dev from your main branch is an anti-pattern. While there are some use cases that use main as a development branch, deployments to dev should be done in a branch. The reason being is that your main branch should be your source of truth. If your code is likely to change between your last push to main to when you tag it, it really should be done in a branch.
A better pattern would be that you push to staging on main, and then production on a tag.
But if you have a business case for your pattern, feel free to ignore me.
I've looked at the instructions here https://learn.microsoft.com/en-us/azure/devops/pipelines/process/environments?view=azure-devops and set up an environment called test. However when I put this environment: test line in the below pipeline I get an error "unexpected value". Where do I need to put the environment: test ?
pr:
branches:
include:
- '*'
trigger:
branches:
include:
- master
pool:
vmImage: ubuntu-latest
stages:
- stage: Build
jobs:
- job: Build
steps:
- template: templates/build.yml
- stage: Release
condition: and(succeeded('Build'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
jobs:
- job: DeployDev
environment: test
variables:
You need to change your ordinary job into a deployment job :
jobs:
- deployment: DeployDev
environment: test
I have the following condition:
name: Build Image
on:
push:
pull_request:
workflow_dispatch:
jobs:
build-image: (This should be only if the tag contains "azure")
name: Build Image Job
runs-on: [ self-hosted ]
steps:
- uses: actions/checkout#v2
- name: Run Build Step
run: |
ANSIBLE_VERSION=$(cat VERSION)
docker images
jobs:
build-image: (This will be for everything else)
name: Build Image Job
runs-on: [ self-hosted ]
steps:
- uses: actions/checkout#v2
- name: Run Build Step
run: |
ANSIBLE_VERSION=$(cat VERSION)
docker images
How can that be achieved? How do you reference the tags inside a job?
How do you the variable and make an if rule out of it?
You can use regex in your on config to trigger a workflow based on a tag name. For example:
on:
push:
tags:
- '*azure*'
At the level of a job or a step, you can use a contains() expression:
jobs:
build-for-azure-tag:
name: build-for-azure-tag
runs-on: ubuntu-latest
if: github.ref_type == 'tag' && contains(github.ref_name, 'azure')