I have a github actions workflow, which lints, builds, tests, releases and deploys the software: common CI/CD steps.
This being a FLOSS project, I want to run some jobs for pull-requests and some only when stuff is pushed to main (master) branch and/or tagged. The latter jobs release and deploy the software, so I want to avoid running those when someone makes a PR at all costs.
For the sake of this question details are omitted and all steps abstracted away in shell scripts. The workflow looks like this:
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
CARGO_TERM_COLOR: always
TAG_FILE: "./job_tags.txt"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Lint
run: lint.sh
build:
runs-on: ubuntu-latest
steps:
- name: Build
run: build.sh
test:
needs: build
runs-on: ubuntu-latest
steps:
- name: Test
run: test.sh
deploy:
needs: [lint, test, build]
if: startsWith(github.ref, 'refs/tags')
runs-on: ubuntu-latest
steps:
- name: Deploy
run: deploy.sh
There are dependencies (needs:) and one if, witch tries to achieve the following:
For all pull_requests to main, run lint, build, test. but not deploy
For all tagged commits to main, run lint, build, test and deploy.
The things I cannot find in the documentation are:
What if someone branches off, creates commits, tags them and then makes a PR. Will that trigger the tags? Do I need extra protection in place to ensure the tag was made on main, of the repo that I hold, and not a fork?
How can I match this on tags with a pattern only? Say v*, only?
Is this feasible in one workflow file? Or should I split the "run for all PRs" and "run only for tagged commits to main" into separate workflows (I'd rather avoid this as it comes with either a lot of complexity -building own reusable actions- or duplication; since I cannot make a job needs: jobs from other workflows).
Is there a function or expression that I'm overlooking which does exactly what I want: filter if this is "my" repo or someone elses in a PR?
Related
I'd like a Github action to run on Pull Request to a specific base branch, but from another specific head branch.
name: Run production tests
on:
push:
pull_request:
branches:
- main
jobs: ...
However, I specifically want something like this to run when a branch called develop is PR'd against main, not just every time something is PR'd to main.
Is such a workflow possible? I might be missing it, but I don't see a way to target head branches in the docs.
From the documentation, I could not find any filters for the head branch. But this is doable with if conditions for jobs.
For example
name: Run production tests
on:
pull_request:
branches:
- main
jobs:
build:
if: ${{ github.head_ref == 'develop'}}
runs-on: ubuntu-latest
steps:
- name: Run a multi-line script
run: |
echo "Do something here"
This is the config.yml file I have created. It has 2 workflows. Smoke tests & cypress-all-tests
version: 2.1
orbs:
cypress: cypress-io/cypress#1
workflows:
pre-merge-run:
jobs:
- cypress/run:
name: Smoke tests
command: npm run cy:smoke
filters:
branches:
ignore:
-main
cypress-all-tests:
jobs:
- cypress/run:
name: All tests
command: npm run cy:all:tests
filters:
branches:
only:
- main
My intention is to run Smoke tests workflow on every pull request before it is merged to the main branch. Then run only cypress-all-tests workflow once the PR is merged to the main branch.
When the config file is run by CircleCI, this is what happens:
Only smoke tests run on the pull request before merge (which is what I want)
BUT
Both the workflows run after the PR is merged to the main branch (which is not what I need). Only the workflow cypress-all-tests should be running now.
I don't know where am I making the mistake.
So it was a silly mistake!
I just had to put a space between - and main. You can see the absence of a space in the screenshot below.
I'm experimenting with setting up GitHub Classroom (after getting really tired of manually running tests for student submissions this term). I picked one of the tests from the class I am just finishing, but for the test script I have there, I need Python 3.10; earlier versions won't do.
I tried setting up .github/workflows/classroom.yml to specify the Python version. If I set it to this, in a student repository, I can get my tests to run:
name: GitHub Classroom Workflow
on: [push]
jobs:
build:
name: Autograding
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python#v2
with:
python-version: "3.10"
- uses: actions/checkout#v2
- uses: education/autograding#v1
but (of course) I don't want my students to do this manually whenever they check out an assignment. So, I tried adding the same to the template repository, but that doesn't seem to affect the student repository when I make a new one of those. There, I get the default I got before
name: GitHub Classroom Workflow
on: [push]
jobs:
build:
name: Autograding
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: education/autograding#v1
Is there a way to specify what the workflow should be for an assignment or classroom? Or a way to get it from the template?
Or a way to get it from the template?
Your template could include a workflow, meaning reuse an existing workflow (possible since Oct. 2021)
The "Reusable workflows and workflow templates" section includes:
Inside workflow templates, you can also reference reusable workflows to make it easy for people to benefit from reusing centrally managed workflow code.
If your reusable workflow comes with the right python-version, nothing will have to be set up manually.
I'm currently using the "git-flow" branching model outlined here. Following that model, once I've completed work on a feature branch, I'd like to add new GitHub actions to that branch (for example, to run my feaure's automated tests) before the branch is merged.
Following the branching model, I don't want to define the actions in a workflow file on the default branch before that feature branch is merged into it. Ideally I want to add the actions on the feature branch itself before the merge, but this doesn't appear to work.
I've added the below sample workflow to my feature branch, but GitHub does not detect it. Am I missing something here, or can workflows only detected and run once they're on the default branch? If the latter is true, do people generally merge their branches, then add workflows for them?
# Name workflow
name: Test workflow
# Read only permissions
permissions: read-all
# Triggered once every 15 minutes
on:
workflow_dispatch:
schedule:
- cron: '15 * * * *'
# Listing of jobs to be run
jobs:
# Just output the Python version for now.
python-tests:
name: Python Tests
runs-on: ubuntu-latest
# Use the environment configured with secrets
environment: python-test-environment
# Set the working directory?
defaults:
run:
working-directory: tests
steps:
# Checkout the repository
- name: Checkout
uses: actions/checkout#v2
ref: 'dev-tests'
# Configure Python
- name: Set up Python 3.7
uses: actions/setup-python#v2
with:
python-version: 3.7
# Output the Python version
- name: Display version
run: python -c "import sys; print(sys.version)"
Update: I can see now that the "schedule" trigger only works on the default branch. However, removing it and just using the workflow_dispatch trigger still (on the feature branch YML file) still does not show the workflow on GitHub.
I have the following .github/workflows/ci.yml file for GitHub Actions (some code removed to make it easier to understand for this question):
name: CI
on:
push:
release:
types: [published]
jobs:
test:
runs-on: ubuntu-latest
steps:
# ...
deploy-staging:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && github.ref == 'staging'
steps:
# ...
I went through the following steps:
Make some commits on the develop branch, and push those changes.
After build passes on GitHub Actions I did a fast forward merge from develop into staging.
I expected GitHub Actions to run both the test and deploy-staging jobs after item 2. But instead it just ran test again without running deploy-staging.
As you can see above even after pushing to staging it still ran it on the develop branch instead of the staging branch. I'm kinda assuming this might be due to some weird behavior with fast forward merges. But GitHub obviously recognized that I pushed to staging as it offered to create a PR from that branch into master.
So that makes me rethink my theory about why it's trying to run on develop instead of staging.
Why would this be happening? Is there anyway to fix this so merging into staging actually runs the workflow on staging as opposed to develop?
My approach would be so separate the triggers and related jobs into different workflows.
So, to mimic your example, instead of a ci.yml I would have two files:
test.yml
deploy-staging.yml
In .github/workflows/test.yml:
name: Test
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
# ...
In .github/workflows/release-staging.yml:
name: Release Staging
on:
push:
branches:
- staging
jobs:
deploy-staging:
runs-on: ubuntu-latest
steps:
# test steps ...
# release ...
Admittedly this is annoying because the release doesn't run on the same test run as the test, but you want to make sure the tests all pass before deploying.
If you wanted to chain the test run workflow to run the deploy workflow I might change release-staging to use the Check suite event instead of push.
${{ github.ref }} will be refs/heads/staging not just staging.
The best thing to do in these situations is simply to echo the variable values you want to check in a step before it:
steps:
- name: Check inputs
run: |
echo github.ref is: ${{ github.ref }}
echo github.event_name is: ${{ github.event_name }}