How to run GitHub workflow on every commit of a push - github-actions

I have some tests that I would like to run on every commit of my repository. I have the following script in my repo:
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- run: echo "my tests"
Unfortunately, if I push some new commits to my repository, the tests are only run against the latest commit. Is there a way to test all commits?

It is possible to to this by checking out individual commits and building each one in a single run: step.
In order to do this, the fetch-depth option for the checkout action needs to be 0 to checkout the full git tree.
I did something like this using GitPython to iterate and checkout each commit.
Using just the git command line tool, the rev-list command could be used to create a list of commits.
The tricky part is figuring out the commit range. For pull requests, GitHub actions provides github.head_ref and github.base_ref properties (docs) that could be used to create the commit range. However, these properties are not available for other events, like push (in that case, github.ref could be used with a fixed branch name like origin/main).
Here is a simple example. It may need more a advanced query for rev-list to handle cases where base_ref is not an ancestor of head_ref, but I will leave that for other SO questions to answer.
name: CI
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
with:
fetch-depth: 0
- run: |
for commit in $(git rev-list ${{ github.base_ref }}..${{ github.head_ref }}); do
git checkout $commit
echo "run test"
done

Building on David Lechner's answer:
name: CI
on:
push:
# only trigger on branches, not on tags
branches: '**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
with:
# checkout full tree
fetch-depth: 0
- run: |
for commit in $(git rev-list ${{ github.event.before}}..${{ github.sha}}); do
git checkout $commit
echo "run test"
done
As per the docs on the github context and the docs on the push webhook event data {{github.event.before}} is replaced by the commit sha before the push. {{github.sha}} or {{github.event.after}} is replaced by the sha of the latest commit that was pushed:
Push event payload (for a pushed tag; docs)
{
"ref": "refs/tags/simple-tag",
"before": "6113728f27ae82c7b1a177c8d03f9e96e0adf246",
"after": "0000000000000000000000000000000000000000",
"created": false,
"deleted": true,
"forced": false,
"base_ref": null,
"compare": "https://github.com/Codertocat/Hello-World/compare/6113728f27ae...000000000000",
"commits": [],
"head_commit": null,
[...]
}

Related

What github action can i use in the event of push to get changes that were a part of the commit that was pushed?

Currently, my GitHub workflow looks as follows:
name: learn-github-actions
run-name: ${{ github.actor }} is learning GitHub Actions
on:
push:
branches:
- main
jobs:
update-x:
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout#v2
with:
# fetch depth is needed since we will be taking git diff with HEAD^1
fetch-depth: 2
- name: Run script
run: scripts/x/x-version-bump.sh
Instead of using git diff in my x-version-bump.sh script I would like to get the changes of the commit pushed via a GitHub action and pass it on to the script. I cannot find a way currently in Github actions to do the same.

Run a certain job depending on the source branch from a PR

I have a GitHub action workflow for a swift package that runs whenever something is merged to the main branch.
My goal is to check the for a source branch and depending on its prefix (i.e. patch/something) determine wow to tag and release it.
This is how I have it configured so far:

name: Release
on:
push:
branches:
- main
jobs:
build:
runs-on: macos-latest
patch-release-on-push:
needs: build
if: contains(github.head_ref, 'patch')
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- id: release
uses: rymndhng/release-on-push-action#master
with:
bump_version_scheme: patch
The problem with this is that github.head_ref is null. I only get a value on it if I switch the workflow to be triggered on a pull_request instead of push which wouldn’t really work given that the release would be out before the PR was merged.

What’s the right approach for achieving this?


I would suggest you to use an existing action like EthanSK/git-branch-name-action, as example:
on: [push, pull_request]
jobs:
main_job:
runs-on: ubuntu-latest
steps:
- name: Git branch name
id: git-branch-name
uses: EthanSK/git-branch-name-action#v1
- name: Echo the branch name
run: echo "Branch name ${GIT_BRANCH_NAME}"
and use also like
if: ${{ contains(env.GIT_BRANCH_NAME, 'patch') }}
Link to the marketplace here

Github action rebase running twice

I want github action to rebase my branch onto main as soon as a PR is created or updated from feature branch onto main branch.
But this rebase workflow ends up running twice.
Following is the code:
name: Rebase on main branch
on:
pull_request:
branches: [ main ]
jobs:
rebase:
name: Rebase on main branch
runs-on: ubuntu-latest
steps:
- name: git checkout
uses: actions/checkout#v2
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
fetch-depth: 0
- name: automatic rebase
uses: cirrus-actions/rebase#1.5
env:
GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
I have another test workflow that runs on successful rebase. Since rebase runs twice, test also runs twice which is not the intended behavior.
How do I make rebase run only once?
Or is there some trigger that can tell me if PR(create or update) + rebase happened?

How to get all the changes of a Pull Request when triggering on pull_request_review?

I currently have a GitHub Action that triggers on:
pull_request_review:
types: [submitted]
I then want to run a command, which expects the contents of changes of the Pull Request.
Previously, I was using
on:
push
and I had no issues with the contents of the files being available in the Action context.
However, my command is failing now, and I think it's because the context only includes the commit that the action was triggered on (no file changes.)
Previously I was running this action on push and that was always successful, with the file changes being available in the context.
I'm using:
steps:
- uses: actions/checkout#v2
(https://github.com/actions/checkout)
Is it possible to use this to have all the file changes on the Pull Request within the Action context?
Any help on this would be appreciated!
You can do that by using an open source Action available on marketplace:
jobs:
build:
runs-on: ubuntu-latest # windows-latest | macos-latest
name: Test changed-files
steps:
- uses: actions/checkout#v2
with:
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files#v14.6
- name: List all changed files
run: |
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
echo "$file was changed"
done
The solution above uses git checkout and git diff to get files changed by PR. Alternatively if you really need just information about paths changed and you don't really need files themselves (no checkout) - you can do it without checkout using gh CLI:
gh pr view XXX --json files -q '.files[].path'
You can run it like this:
jobs:
comment:
runs-on: ubuntu-latest
steps:
- run: gh pr view XXX --json files -q '.files[].path'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Tag a different branch than master on pull request

I'm new at github actions and there's something I clearly don't understand, so hoping for some help. I've inherited a repo with a workflow consisting of a number of steps, and while I'm getting the overall picture, there's also a part just not working.
What I want to achieve
My workflow builds a number of containers and a binary. These are uploaded to different places, all with version number and tag matching. This works great for a release as everything is tagged properly and references each other. However, I want this to work for an unmerged pull-request as well - this would give the possibility to test things properly.
The problem
The github repo is tagged, but it is always the HEAD of master getting tagged, also on pull requests. For pull requests, I expect the commit of the PR branch to get tagged - but nope.
The workflow below runs as I expect it to - the pre-release step runs for pull request actions, while the release steps runs when the pull request is merged. However, for each pull request action, the HEAD of master is tagged with the generated tag.
Workflow
on:
push:
branches:
- "master"
pull_request:
branches: [ master ]
jobs:
tag:
runs-on: ubuntu-latest
outputs:
name: ${{ steps.generate_tag.outputs.name }}
steps:
- uses: actions/checkout#v2.3.4
with:
ref: ${{ github.sha }}
- name: Generate tag name
id: generate_tag
run: echo "::set-output name=name::v$(date -d "$(git show -s --format=%ci)" +'%Y.%-m.%-d-%-H%M%S')"
go:
runs-on: macos-latest
needs: [tag]
steps:
- uses: actions/checkout#v2.3.4
with:
ref: ${{ github.sha }}
- name: Tag actual releases as releases
if: "contains(github.ref, 'master')"
run: |
git config user.name "GitHub Actions"
git config user.email noreply#github.com
git tag "${{ needs.tag.outputs.name }}" -m "Version: ${{ needs.tag.outputs.name }}"
git checkout "${{ needs.tag.outputs.name }}"
git branch
- name: Tag PRs as prerelease
if: "!contains(github.ref, 'master')"
run: |
git config user.name "GitHub Actions"
git config user.email noreply#github.com
git tag "${{ needs.tag.outputs.name }}"
git checkout "${{ needs.tag.outputs.name }}"
git branch
On Pull Request event trigger from any branch to master the ref: ${{ github.sha }} does not point to the last commit of that branch. Since you're using push and pull_request events for master and other branches then you should be able to just remove the usage of ref during actions checkout step.
Try the following step to checkout current branch code that generated the event. The following will be your branch latest commit on pull request, and it will be master after commit merged during the push event.
- uses: actions/checkout#v2.3.4
You can find more about github actions here topics here