How to run jobs based on the pull request branch - github

I have 2 jobs in my workflow 'Plan and Apply". I want plan to run when there is pull request on my testing branch and Apply to run when there is a pull request on master branch. Below is the snippet of my code. This workflow doesn't run,I am getting message " This check was skipped" .What I'm i doing wrong?
on:
pull_request:
branches:
- testing
- master
jobs:
plan:
name: "Terraform Plan"
if: ${{ github.head_ref == 'testing'}}
Apply:
name: "Run Terraform Apply"
if: ${{ github.head_ref == 'master'}}

I'd recommend to instead of putting it all into one workflow file, to create two separate ones, where you then only specify the branch you want, for example:
`plan_testing.yml`
on:
pull_request:
branches:
- testing
jobs:
plan:
name: "Terraform Plan"
This achieves the same outcome while keeping them more easily separated and simpler to audit their run history in GitHub Actions.
You can find out more about GitHub Actions and how to configure them by checking out their awesome docs.

Related

Losing the source branch of triggering build pipeline in Azure DevOps deployment pipeline

In Azure DevOps, I have two Git repositories in the MyProject project:
MyProject.Web is the .NET Core server-side code for an Angular application.
MyProject.UI is the associated Angular project.
Pull requests to specified branches in both of those projects trigger a build pipeline. The pipeline YAML files are in the MyProject.Web repo. Successful completion of the build pipeline triggers a deployment pipeline. The build is working fine; the deployment is fine when a MyProject.Web branch is the trigger, but it isn't always doing what's expected when a MyProject.UI branch is the trigger.
Details
We currently have three deployment environments: Dev, QA, Test.
I have a build pipeline that pulls the code from each of these repos together and builds the application (into a Docker image, for what it's worth).
That pipeline is triggered by completed pull requests to any master or main or release/* branch in either the Web or UI repo. (In the Web project, it's master;
in the UI project, it's main). Whether the trigger comes from the Web repo or the UI repo, the pipeline knows to combine it with the corresponding branch
from the other repo (i.e., master with main, main with master, release/1.0 with release/1.0, release/1.2 with release/1.2, etc.).
I have a deployment pipeline that is triggered by completion of the build pipeline. It has one stage per deployment environment It is supposed to know whether the source branch was master or main or whether it was a release/* branch.
If it was master or main, it should deploy to Dev and, after manager approval, to QA. It should never deploy to Test.
If it was a release/* branch, it should deploy, after manager approval, to Test. It should never deploy to Dev or QA.
Expectations in Each Triggering Scenario
Here is a summary of my expectations/requirements for each possible type of build trigger, and the reality in the deployment in the fourth scenario.
TriggeringProject
TriggeringBranch
MyProject.Web Branchto Build
MyProject.UIBranchto Build
MyProject.WebBranch toDeploy From
Environment(s) toDeploy To
MyProject.Web
master
master
main
master
Dev, QA
MyProject.Web
release/1.0
release/1.0
release/1.0
release/1.0
Test
MyProject.UI
main
master
main
master
Dev, QA
MyProject.UI
release/1.0
release/1.0
release/1.0
release/1.0 ❌(reality: seems to pullfrom master)
Test ❌(reality: deploysto Dev, QA)
The Problem
My setup performs as expected, as set out in the table, except for the deployment process for the final case. While I can tell from the DevOps pipeline logs that the builds are
correctly choosing the branches to get the code from in all four scenarios, the deployment in the final scenario seems to be taking a build associated
with the MyProject.Web master branch (the log shows that the pipeline was run against master) and it is deploying whatever build it's finding on master to Dev and QA instead of to Test.
Any thoughts about what's going on here? Guidance for a solution? Details below.
The Pipeline Files
Three pipeline files come into play here:
docker-build.yml, the YAML file behind a pipeline named Docker-Build.
It resides in MyProject.Web.
It is triggered by completed pull requests to master or release/* branches on MyProject.Web.
It is also triggered by completed PRs to main or release/* branches on MyProject.UI.
After setting things up and setting template parameter values, the meat of its work is performed by an invoked pipeline template, but there's no need to go into that here.
kubernetes-deploy.yml, the YAML file behind a pipeline named Kubernetes-Deploy.
It resides in MyProject.Web.
It is triggered by successful completion of Docker-Build.
After setting things up and setting one template parameter value (the pipeline ID of the associated Docker-Build pipeline), it invokes the pipeline template deploy-pipeline-template.yml, discussed next.
deploy-pipeline-template.yml, a pipeline template.
It is shared by multiple applications/repos in this same project.
It resides in a separate repository called MyProject.Pipeline.
The content of these files, with extraneous omissions noted:
docker-build.yml:
# This is the YAML for the "Docker-Build" pipeline. It resides in the MyProject.Web repository.
resources:
repositories:
- repository: self
type: git
name: MyProject.Web
trigger:
- master
- release/*
- repository: UiRepo
type: git
name: MyProject.UI
trigger:
- main
- release/*
- repository: PipelineRepo
type: git
name: MyProject.Pipeline
# [variables and pool omitted]
steps:
- ${{ if in(variables['Build.SourceBranchName'], 'master', 'main') }}:
- checkout: git://MyProject/MyProject.Web#refs/heads/master
- checkout: git://MyProject/MyProject.UI#refs/heads/main
- ${{ if not(in(variables['Build.SourceBranchName'], 'master', 'main')) }}:
- checkout: git://MyProject/MyProject.Web#${{ variables['Build.SourceBranch'] }}
- checkout: git://MyProject/MyProject.UI#${{ variables['Build.SourceBranch'] }}
# [some details omitted]
- template: build-pipeline-template.yml#PipelineRepo
parameters:
relativeSolutionPath: MyProject.Web
relativeProjectPath: MyProject.Web/MyProject.Web
# [other parameters omitted]
kubernetes-deploy.yml:
repositories:
- repository: PipelineRepo
type: git
name: MyProject.Pipeline
pipelines:
- pipeline: buildPipeline
source: 'Docker-Build'
trigger: true
trigger:
- none
# [pool omitted]
stages:
- template: deploy-pipeline-template.yml#PipelineRepo
parameters:
buildPipelineId: '123'
# I can probably replace '123' with variables['resources.pipeline.buildPipeline.PipelineID'] or the
# same thing with another one of Azure DevOps' multitudinous syntaxes, but I haven't tested it yet.
build-pipeline-template.yml
# This is a pipeline template that resides in the MyProject.Pipeline repository.
parameters:
- name: buildPipelineId
displayName: ID of the pipeline that produced the artifacts to download
type: string
stages:
- template: deploy-pipeline-job-template.yml
parameters:
stageName: Development
canRun: and(not(or(failed(), canceled())), in(variables['resources.pipeline.buildPipeline.sourceBranch'], 'refs/heads/master', 'refs/heads/main'))
variableGroup: myproject-web-variables-dev
buildPipelineId: ${{ parameters.buildPipelineId }}
devOpsEnvironment: myproject-dev
kubernetesServiceConnection: myproject-dev-kubeconfig
- template: deploy-pipeline-job-template.yml
parameters:
stageName: QA
canRun: and(not(or(failed(), canceled())), in(variables['resources.pipeline.buildPipeline.sourceBranch'], 'refs/heads/master', 'refs/heads/main'))
variableGroup: myproject-web-variables-qa
buildPipelineId: ${{ parameters.buildPipelineId }}
devOpsEnvironment: myproject-qa
kubernetesServiceConnection: myproject-dev-kubeconfig
- template: deploy-pipeline-job-template.yml
parameters:
stageName: Test
canRun: and(not(or(failed(), canceled())), startsWith(variables['resources.pipeline.buildPipeline.sourceBranch'], 'refs/heads/release/'))
variableGroup: myproject-web-variables-test
buildPipelineId: ${{ parameters.buildPipelineId }}
devOpsEnvironment: myproject-test
kubernetesServiceConnection: myproject-dev-kubeconfig

Formatting Kubernetes logs as part of Github Actions workflow

I have one particular workflow that deploys a service and then if an error occurs, logs should be outputted. In a separate workflow file called tests.yml, I have the following:
name: TESTS
on: pull_request
jobs:
run_tests:
runs-on: ubuntu-latest
steps:
- name: View Logs
if: ${{ failure() }}
run: |
kubectl -n dev logs dev/my-service
Is there any way I can improve the way logs are displayed on Github? Highlighting or any formatting action I can apply? They are quite dense and I am searching for a way in which I can make them more readble. Any help, documentation, example will be greatly appreciated.
Thank you

How to trigger GitHub Action workflow based on several workflows

Suppose i have three workflows: build_backend, build_frontend and deploy. First two should trigger in parallel, but the third should only trigger when both of those workflows are finished.
Currently the deploy workflow triggers twice -- i suspect that's for each of the two workflows completed.
# .github/workflows/build-xxx.yml
name: Build and Test - Backend
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v2
# ...
# .github/workflows/deploy.yml
name: Deploy
on:
workflow_run:
workflows:
- "Build and Test - Backend"
- "Build and Test - Frontend"
types:
- completed
branch: master
jobs:
deploy:
# ...
I haven't found the solution in docs:
https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_run
https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
GitHub actions does not support specific trigger definitions like this for whole workflows.
However, you can use the needs keyword on a job level. So if you could consolidate all of these workflows into one workflow file. It seems like like this could work for you since these workflows all have the same (branch) trigger and the buildxxx are only a single job each.
There is also a GitHub Roadmap item describing, that they are working on adding workflow partials. That would enable you to separte these parts out in the future if you want to, but that is not avilable yet it seems like.

github actions: Push several times, but I want the build to be done only for the last push

name: master builder
on:
push:
branches:
- master
~~~
I have a workflow like this. So, Whenever I push to the master branch, the actions run.
But I want the build to work only on the last push.
For example,
master branch - feature1 (person1)
master branch - feature2 (person2)
master branch - feature3 (person3)
In this structure, if features1,2,3 are merged at almost the same time, the build will run 3 times.
But I want the master branch to be built only on the last merge. Just once.
Is there anyway to do this? like.. run the build only once after waiting for about 1 minute when pushing.
This is a sample code that I proceeded in the way you answered. But I get an error "The key 'concurrency' is not allowed". What's wrong?
name: test
on:
push:
branches:
- feature/**
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
jobs:
~~~
You may try to achieve this with concurrency and cancel-in-progress: true
Concurrency ensures that only a single job or workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can only use the github context. For more information about expressions, see "Context and expression syntax for GitHub Actions."
You can also specify concurrency at the job level. For more information, see jobs.<job_id>.concurrency.
When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. Any previously pending job or workflow in the concurrency group will be canceled. To also cancel any currently running job or workflow in the same concurrency group, specify cancel-in-progress: true.
However
Note: Concurrency is currently in beta and subject to change.
Here is an example workflow:
name: Deploy
on:
push:
branches:
- main
- production
paths-ignore:
- '**.md'
# Ensures that only one deploy task per branch/environment will run at a time.
concurrency:
group: environment-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Extract commit
run: |
echo "Sending commit $GITHUB_SHA for $GITHUB_REPOSITORY"

Azure DevOps - Pull Request Workflow and Deployments

I'm a bit confused with how to set this workflow up using pull requests.
I have in place an existing multi-stage YAML build pipeline that in summary does the following:
Runs a build from any branch
Runs a deployment job to a Development Environment/Resource, if the source branch is feature/* or release/* and the build succeeds
Runs a deployment job to a UAT Environment/Resource, if the source branch is release/*
Runs a deployment job to Live/Production Environment/Resource, if the source branch is master
So off the back of CI this workflow seems to work fine, the correct stages are run depending on the branch etc.
I then decided that branch policies and pull requests might be a better option for code quality rather than let any of the main branches be direct committed to, so I started to rework the YAML to account - mainly by removing the trigger to
trigger: none
This now works correctly in line with a branch policy, the build only gets kicked off when a pull request on to develop or master is opened.
However this is then where I'm a bit confused with how this is supposed to work and how I think it works ....
Firstly - is it not possible to trigger the multi-stage YAML off the back of pull requests (using Azure Repos) ? In my head all I want to do is introduce the pull request and branch policies but keep the multi-stage deployments to environments as is.
However, the deployment job stages all get skipped now - but this might be to do with my conditions within the YAML, which are as follows:
- stage: 'Dev'
displayName: 'Development Deployment'
dependsOn: 'Build'
condition: |
and
(
succeeded()
eq(variables['Build.Reason'], 'PullRequest'),
ne(variables['System.PullRequest.PullRequestId'], 'Null'),
or
(
startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/'),
startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')
)
)
jobs:
- deployment: Deploy
pool:
name: 'Development Server Agent Pool'
variables:
Parameters.WebsitePhysicalPath: '%SystemDrive%\inetpub\wwwroot\App'
Parameters.VirtualPathForApplication: ''
Parameters.VirtualApplication: ''
environment: 'Development.Resource-Name'
.....
Is there something I am missing?
Or do I have to remove the multi-stage deployments from YAML and revert back to using Release Pipelines for pull requests (maybe with approval gates??)
Thanks in advance!
It looks like the issue of the conditions within the YAML.
If the pipeline is triggered by a PR. the value variables['Build.SourceBranch'] will be refs/pull/<PR id>/merge. The express in above condtion startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/') will be false, which caused the stage to be skipped. See build variables for more information.
You can try using variables['System.PullRequest.SourceBranch'], which will be evaluated to the value of the source Branch of the PR. Check System variables for more information. See below:
condition: |
and
(
succeeded(),
eq(variables['Build.Reason'], 'PullRequest'),
ne(variables['System.PullRequest.PullRequestId'], ''),
or
(
startsWith(variables['System.PullRequest.SourceBranch'], 'refs/heads/feature/'),
startsWith(variables['System.PullRequest.SourceBranch'], 'refs/heads/release/')
)
)