I have 2 workflows
First runs tests and generated allure report and second builds and deploys to github pages and sends a slack notification with the link to gh pages.
I am curious, how can I get run number of the first workflow and pass it to the second workflow as ${{github.run_number}}?
I've tried to pass just ${{github.run_number}}
You can configure the first WF to trigger the second WF and pass some inputs. At first, you need to define an input in the second workflow:
name: Second workflow (deploy)
on:
workflow_dispatch:
inputs:
run_number: # Exposing the input through which we can pass the value
description: 'The run number'
required: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Echo the input
run: echo ${{ github.event.inputs.run_number }}
Then, you can trigger this workflow from another workflow in the following way:
name: First Workflow (report)
on:
push:
branches:
- '*'
jobs:
allure-report:
runs-on: ubuntu-latest
steps:
# ... Allure report generation steps, etc.
- name: Invoke the deploy WF
uses: benc-uk/workflow-dispatch#v1
with:
workflow: deploy.yaml
inputs: '{ "run_number": "${{ github.run_number }}" }'
In this example, I've used the Workflow Dispatch GH Action to pass the current run_number to the deploy.yml WF as an input value.
To read more about workflow inputs see the Specifying inputs and workflow_dispatch event.
I'm trying to get this github action to work but once committed it gives me this error:
Invalid workflow file: .github/workflows/main.yml#L1
No steps defined in steps and no workflow called in uses for the following jobs: build
Anyone have any idea what this might depend on?
Below is the code I used:
name: Deploy to Cloud Foundry
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-18.04
# Build your app here
deploy:
runs-on: ubuntu-18.04
needs: build
steps:
- uses: citizen-of-planet-earth/cf-cli-action#master
with:
cf_api: https://api.my-cloud-foundry.com
cf_username: ${{ secrets.CF_USER }}
cf_password: ${{ secrets.CF_PASSWORD }}
cf_org: AwesomeApp
cf_space: Development
command: push -f manifest-dev.yml
Thanks in advance to everyone
Following the Workflow Syntax for Github Actions, you'll identify that some fields are mandatory.
At the workflow level, you need to have at least a trigger (configure with the on field) and a list of jobs specified.
Then, in that list of jobs, you have to specify at least one job, where each of those jobs needs at least the runner and the steps (or the uses for reusable workflow) field configured.
Example of the minimum configurations you would use for a job:
on: push
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: Print a greeting
run: echo 'Hello World'
job2: # reusable workflow scenario
uses: owner/repo/.github/workflows/reusable-workflow.yml#main
I have got two workflows:
workflow1.yaml
workflow2.yaml
I need in workflow2.yaml add something like:
jobs:
build_kotlin:
runs-on: [server1, server2, server3]
needs: [workflow1]
steps:
- name: Checkout code
uses: actions/checkout#v2
Currently "needs" doesn't work properly. How can reference separate workflow yaml file?
needs is only used to establish relationships between jobs -- not entire workflows.
If you want to run "workflow2.yaml" after "workflow1.yaml" has been completed, then add a trigger like so:
on:
workflow_run:
workflows: [workflow1]
types:
- completed
jobs:
build_kotlin
# ...
Read more on Events That Trigger Workflows
Alternatively, you could make workflow1 a reusable workflow and then make sure it is executed before workflow2 like so:
jobs:
workflow1:
uses: octo-org/example-repo/.github/workflows/workflow1.yaml#main
build_kotlin:
runs-on: [server1, server2, server3]
needs: [workflow1]
steps:
- name: Checkout code
uses: actions/checkout#v2
I have a branch called stage and currently have a workflow that runs when a PR is labeled (to merge into the stage branch), and I'm currently trying to create a workflow that happens if the branch is successfully automerge.
For example -- here's a working example of the workflow to the stage branch:
name: PR opened to stage
on:
pull_request:
types: [labeled]
branches: [ stage ]
jobs:
audit-checks:
runs-on: self-hosted
steps:
- uses: actions/checkout#v2
if: contains(github.event.pull_request.labels.*.name, 'ready')
- name: Enable Auto Merge
uses: peter-evans/enable-pull-request-automerge#v1
if: contains(github.event.pull_request.labels.*.name, 'ready')
with:
token: ${{ secrets.GITHUB_TOKEN }}
pull-request-number: ${{ github.event.pull_request.number }}
merge-method: merge
And here's another workflow that, when a PR to stage is closed, is supposed to run. I have a step as well that checks to see if the label includes ready and is supposed to create another PR to another branch:
name: ready for prod test
on:
pull_request:
types: [closed]
branches: [ stage ]
jobs:
audit-checks:
runs-on: self-hosted
steps:
- uses: actions/checkout#v2
- name: automate PR creation for prod
if: |
${{ github.event.pull_request.merged }} && contains(github.event.pull_request.labels.*.name, 'ready')
uses: peter-evans/create-pull-request#v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: stage
base: prod
labels: ready
title: Automated PR opened
It seems that when the PR is initially opened and labeled ready, the first workflow runs just fine. However, once that workflow enables auto merge and it actually auto-merges (upon completion of the workflow), the second workflow doesn't ever get triggered.
Is it possible that the second workflow is somehow running before the first one completes and doesn't actually do anything because of it? I'm not sure it's anything in my 2nd job (at least not yet) since it hasn't even run (or run and fail).
Just found my answer here: https://docs.github.com/en/actions/security-guides/automatic-token-authentication
When you use the repository's GITHUB_TOKEN to perform tasks on behalf
of the GitHub Actions app, events triggered by the GITHUB_TOKEN will
not create a new workflow run. This prevents you from accidentally
creating recursive workflow runs. For example, if a workflow run
pushes code using the repository's GITHUB_TOKEN, a new workflow will
not run even when the repository contains a workflow configured to run
when push events occur.
I'm relatively new to GitHub Actions and I have 2 jobs–one that runs my tests, and one that deploys my project onto a server.
Obviously I want the tests to run on every branch, but deploying should only happen when something gets pushed to master.
I'm struggling to find a way to run a job on a specific branch. I know it's possible to only run entire workflows on a specific branch, however that would mean I would have a "test" workflow and a "deploy" workflow.
This sounds like a solution, however they would run parallel. In an ideal world, the tests would run first, and only if they succeed, then the deploy job would start. This isn't the case when using 2 separate workflows.
How would I be able to achieve this? Is it possible to run jobs on a specific branch?
In a recent update you can now put if conditionals at job level. See the documentation here. https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idif
I tested this workflow which runs the job test on every push, but only runs deploy on the master branch.
name: my workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Execute tests
run: exit 0
deploy:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/master'
steps:
- name: Deploy app
run: exit 0
What follows is my original answer, and an alternative solution if you prefer to have separate workflows.
The first workflow runs for every branch except master. In this workflow you run tests only.
on:
push:
branches:
- '*'
- '!master'
The second workflow runs for just master and runs both your tests and deploys if the tests were successfully passed.
on:
push:
branches:
- master
Most answers provide a solution for one single branch. To restrict the job to run on any specific set of branches, you can do it using the if conditional with multiple disjunction (||) operators; but this is too verbose and doesn't respect the DRY principle.
The same can be archived with less repetition using the contains function.
Using contains:
contains('
refs/heads/dev
refs/heads/staging
refs/heads/production
', github.ref)
compared to using multiple ||:
github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/staging' || github.ref == 'refs/heads/production' || …
Full example:
---
on: push
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Run tests
run: …
deployment:
name: Deployment
runs-on: ubuntu-latest
needs: [test]
if:
contains('
refs/heads/dev
refs/heads/staging
refs/heads/production
', github.ref)
steps:
- uses: actions/checkout#v2
- name: Deploy
run: …
Here is what I've done for steps that should only run on a specific branch.
- name: Publish Image
# Develop branch only
if: github.ref == 'refs/heads/develop'
run: |
... publish commands ...
2021 update
I know it's possible to only run entire workflows on a specific
branch, however that would mean I would have a "test" workflow and a
"deploy" workflow.
This sounds like a solution, however they would run parallel. In an
ideal world, the tests would run first, and only if they succeed, then
the deploy job would start. This isn't the case when using 2 separate
workflows.
You can now use the event workflow_run to achieve the part the tests would run first, and only if they succeed, then the deploy job would start (read on to see how):
Documentation page of workflow_run
https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#workflow_run
This event occurs when a workflow run is requested or completed, and
allows you to execute a workflow based on the finished result of
another workflow. A workflow run is triggered regardless of the result
of the previous workflow.
For example, if your pull_request workflow generates build artifacts,
you can create a new workflow that uses workflow_run to analyze the
results and add a comment to the original pull request.
Now, considering OP's initial issue:
I want the tests to run on every branch, but deploying should only happen when something gets pushed to master
This now could be solved like this:
The following setup is working, a few minutes ago I just implemented the same logic in one of my repository
Workflow <your_repo>/.github/workflows/tests.yml
name: My tests workflow
on:
push:
branches:
- master
pull_request: {}
jobs:
test:
# ... your implementation to run your tests
Workflow <your_repo>/.github/workflows/deploy.yml
name: My deploy workflow
on:
workflow_run:
workflows: My tests workflow # Reuse the name of your tests workflow
branches: master
types: completed
jobs:
deploy:
# `if` required because a workflow run is triggered regardless of
# the result of the previous workflow (see the documentation page)
if: ${{ github.event.workflow_run.conclusion == 'success' }}
# ... your implementation to deploy your project
Although this discussion is very old but recently I came across the same problem with a slight addition. if condition to check whether the branch is main works but what if someone pushes their branch and updates the workflow yml file to remove the if condition? The deploy job will get triggered without their branch even being reviewed or merged in main and could potentially break the production environment. This could be a concern in open source projects.
I couldn't find an answer for this anywhere so wanted to share my findings. I hope this is the right thread for it.
To ensure that there's no way a job is triggered except for in specific branches, environments can be used. A deploy job will most likely have some api keys to connect to the destination server that might be stored in secrets. Instead of storing them in repository secrets which are accessible globally within the repository, we should store them in respective environments.
The official docs for environments contain detailed explanation with sample scripts but sharing a simple example here. Let's say we want to run production deployment only when main is updated
From repository Settings, create a production environment
Choose Selected Branches in Deployment Branches dropdown and add main in the pattern
Add the api keys in production environment secrets
In the workflow yml we just need to add environment information environment: production as follows (using script from #peterevans's answer)
name: my workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Execute tests
run: exit 0
deploy:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: Deploy app
run: exit 0
The environment information indicates where the secrets have to be read from. If the current branch name doesn't match the pattern provided in Selected Branches then the job will immediately fail with an error. Since we have a condition to only run this on main, normally that won't bother us because this job will be skipped on other branches anyways. But if someone, mistakenly or with ill intentions, modifies the yml file and removes the condition before pushing their branch, they'll get an error. So, our system remains secure at least from the threat here.
Hope this helps anyone wondering the same.
The following worked for me inside a job:
Where a PR target branch is one of the following:
if: contains(github.base_ref, 'staging')
|| contains(github.base_ref, 'production')
When the source branch of the pull request is one of them below:
if: contains(github.head_ref, 'feature')
|| contains(github.head_ref, 'release')
name: CI
on: push
jobs:
prod-check:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to production server on branch $GITHUB_REF"
According to the documentation, the if condition is wrapped like so
if: ${{ github.ref == 'refs/heads/main' }}
While you can't have conditions at job level at this moment, you can have conditions at step level - see Contexts and expression syntax for GitHub Actions.
For getting a branch name, current solution is to check GITHUB_REF environment variable - see Default environment variables and this question for details.
Putting it all together - if you decide to go with accepted answer in last link, your workflow might look like this:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run tests
run: ./my-tests.sh
deploy:
runs-on: ubuntu-latest
needs: test
steps:
- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/})"
id: extract_branch
- name: Deploy
run: ./deploy.sh
if: steps.extract_branch.outputs.branch == 'master'
If you'd rather keep everything in workflow file instead of separated script, you can always add if to each step in given job.
I hope it's just a temporary solution/workaround, and job conditions are going to be added before end of beta.
For steps or jobs you can also use github.ref_name which is the branch or tag name that triggered the workflow run.
name: my workflow
on: push
jobs:
if: github.ref_name == 'main'
test:
runs-on: ubuntu-latest
steps:
- name: Execute tests
run: exit 0
For more information about the github context check here.
You need to add these two script to the workflows
//main.yml
name: main
on:
push:
branches:
- main
//size.yml
name: size
on:
pull_request:
branches:
- main
There are already some pretty good answers. Here's a way to specify multiple branches in your conditional:
name: my workflow
on: push
jobs:
deploy:
if: contains(fromJson('["refs/heads/master", "refs/heads/main"]'), github.ref)
runs-on: ubuntu-latest
steps:
- name: Execute tests
run: exit 0
2022
Below workflow runs only for push in main branch:
name: Distribute to Firebase
on:
push:
branches: [ main ]
jobs:
...