I am just getting started with Github actions. In my test workflow I am firing the workflow on PRs to the develop branch.
on:
pull_request:
branches:
- develop
This works fine, but my question is what branch is being built when this runs. Because this action runs before the merge is actually complete (on PR creation) is it just building the source branch? If so, how is that helpful since it isn't taking the changes the PRs code will make to the target branch.
If it is building the target branch it doesnt make sense because the code isn't actually merged yet.
If you check the documentation for the pull_request event it tells you what the environment variables GITHUB_SHA and GITHUB_REF will be for this event.
GITHUB_SHA: Last merge commit on the GITHUB_REF branch
GITHUB_REF: PR merge branch refs/pull/:prNumber/merge
ref: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request
When you use the official actions/checkout action, these are the settings it uses by default if you don't supply any inputs.
What that means is that by default, pull_request events will checkout a merge commit from the pull request head to the base. This allows you to test against what the source would look like if it was already merged.
Related
I have a mono repo project on GitHub which looks like this:
main_directory/apps/app_A
main_directory/apps/app_B
To create builds for app_A, I have a GitHub action which is configured as follows:
// build_app_A.yml
name: Build App A
on:
push:
paths:
- "apps/app_A/**"
- ".github/workflows/build_app_A.yml"
workflow_dispatch:
inputs:
ref:
description: "Git reference (commit, branch, or tag) to build"
required: true
default: "main"
...
Adding the on -> push -> paths thing makes sure that this GitHub action runs only when files inside the app_A subdirectory change, or when this workflow file itself changes.
This works fine. But there is a problem which is making it run redundantly.
Say I have a PR for app_B and this pull request has changes only inside the apps/app_B folder.
This pull request became stale and I decide to rebase it on top of the main/master branch. The main/master branch has commits related to app_A and my app_B PR is behind these commits.
Now when I rebase this PR's branch and push it, even though the resulting diff has no changes related to app_A compared to the main/master branch, this GitHub action still runs.
My assumption was that given the paths inside my action, the action will run only when the git diff shown on GitHub has changes inside the specified paths, but this doesn't seem to be the case.
What am I missing here? Is there a way I can avoid these redundant builds?
I am able to run workflows on GitHub fine. But I don't want my git history to contain anything unrelated to the development of the software, and nothing specific to any one code hosting site, e.g., GitHub. Basically I don't want to add and track .github/workflows/ in my git repo.
Thinking it would work, I created a separate branch, gh-actions, and added the .github/workflows/main.yml there.
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches: [ master ]
jobs:
<snip>
But apparently this workflow won't even be registered by GH. So I added gh-actions branch to on: push: branches. After pushing this branch to GH, the workflow was registered (checked with gh workflow list).
Now I went to run it on the default branch and got error.
$ gh workflow run .github/workflows/main.yml --ref master
could not create workflow dispatch event: HTTP 422: Workflow does not have 'workflow_dispatch' trigger (https://api.github.com/repos/3N4N/TwitchRecover/actions/workflows/14900813/dispatches)
Apparently workflow_dispatch event only works if it's in the default branch.
I'm now out of ideas. One final way is to change the default branch to gh-actions so that the workflow can be run on master branch, but that would mean that cloning this repository would by default clone the gh-actions branch, and I would rather not deal with that.
If anyone else has any idea, I'd be glad to try it.
I have created on my main branch with
on:
push:
branches: [ test ]
I have noticed, that while I can trigger it manually, and it will work, it will not actually trigger if I push to test. For that, I needed to create that same action file on test. Now, it seems like I don't even need to have the action on the main branch, is that correct?
So why does even the option so specify the branch that it should trigger on exist? It only triggers on the branches the file exists anyway. That said, I found it frustrating that I have to merge my one file from main to my test branch, is there a way to trigger the action automatically on push even if I do not have it on my test branch, only on main?
No, it's not possible. The order of operations in a workflow run triggered by push or pull request is described in the reference documentation:
An event occurs on your repository. The event has an associated commit SHA and Git ref.
GitHub searches the .github/workflows directory in your repository for workflow files that are present in the associated commit SHA or Git ref of the event.
A workflow run is triggered for any workflows that have on: values that match the triggering event. Some events also require the workflow file to be present on the default branch of the repository in order to run.
I have a repository in GitHub and I want to create an Action to build a Docker image and push it to the DockerHub. I know how to do it but if I create the action in a branch other than master, GitHub does not run it.
This is a known problem (Workflow files only picked up from master?).
Any ideas to fix it?
According to the official GitHub Actions documentation (About workflow events):
The following steps occur to trigger a workflow run:
An event occurs on your repository, and the resulting event webhook has an associated commit SHA and Git ref.
The .github/workflows directory in your repository is searched for workflow files at the associated commit SHA or Git ref. The workflow files must be present in that commit SHA or Git ref to be considered.
For example, if the event occurred on a particular repository branch, then the workflow files must be present in the repository on that branch.
The workflow files for that commit SHA and Git ref are inspected, and a new workflow run is triggered for any workflows that have on: values that match the triggering event.
The workflow runs on your repository's code at the same commit SHA and Git ref that triggered the event. When a workflow runs, GitHub sets the GITHUB_SHA (commit SHA) and GITHUB_REF (Git ref) environment variables in the runner environment. For more information, see "Using environment variables."
Because of this, in order to test the workflows we need to perform a git action (ie. do push) in the created branch.
What has worked for me (through trial and error)
Create an empty YAML file in the .github/workflows folder
Create a PR to move that file to your branch
In your branch, you can now do the necessary edits to get your GH Action up & running. NOTE: next to updating your YAML, you also need to make a change
that actually triggers the workflow (I am using the below trigger, note the absence of the '.github' path trigger).
on:
push:
paths:
- 'path/to/your/code/**'
on:
push:
branches:
- "YOUR-TEST-BRANCH"
pull_request:
branches:
- "main"
paths:
- ".github/workflows/test.yaml"
To put it in "BDD" terms:
Background:
Given I'm contributing to a GH repo
When I create a pull request
Then Travis should build the latest commit
When I push to an existing pull request
Then Travis should build the latest commit
When I merge a pull request to master
Then Travis should build master
I was confused by Travis-CI's "build pushes" and "build PRs" settings, as:
Enabling both causes each Pull Request to be build twice by Travis
once for the commit on that branch
and once again for the merge commit of that branch into its destination
Enabling just "build PRs" causes PRs to be built, but doesn't result in post-merge builds (i.e. on master).
Enabling "pushes" brute-force satisfies the above criteria by building all pushes to the repo. You can try to finagle things by white- & black-listing branches, but that will probably bite you unless you're rigorously disciplined with branch names.
This is explained more in Travis-CI docs and GH issue #3241.
Anyone know a configuration that satisfies the above criteria?
I eventually found another GH issue (#2111) which gave me the idea to try enabling both PRs & pushes, but with a whitelist to restrict pushes to a specific branch. This seems to satisfy the criteria for my workflow. Here's what I did:
Enable both PRs & branch pushes in the Travis settings for the repo:
Change .travis.yml to white-list master branch (i.e. only build pushes to master):
branches:
only:
- master
Test it by creating a PR with the .travis.yml change, and another PR with some empty commits to verify it works for forks too.
Verify successful merge commit build from master.
Just found in travis docs
Add to .travis.yml
if: type = push
alternatively:
if: type = pull_request
Assuming you want to build all PRs, something like the following will do the trick. Enable both branch and PR builds on the settings page, and put this line as the first line in your travis.yml:
if: (type = push AND branch IN (master, dev)) OR (type = pull_request AND NOT branch =~ /no-ci/)
This will attempt a push build on all pushes and a PR build on all pushes to an open PR, but will filter out any that don't meet the condition. You might need to modify this a bit - the clause about not building branches with no-ci somewhere in their name is obviously optional, and you may not have two branches that you always want to run builds on.
You can read more on conditions and conditional builds on Travis's site.
The whitelist approach described in the accepted answer has some significant limitations. In particular, it doesn't support non-redundantly building arbitrary branches without opening a PR.
I opened an issue asking for a better solution.
You can use next workflow if you want to test not only master branch but some others branches too:
Keep both "Build pushes" and "Build pull requests" ON
Add branches:except directive to your .travis.yml:
branches:
except:
- /^pr\..*/
In this configuration:
any commit to branch feature-A will trigger the build
any commit to branch pr.feature-A will not trigger the build
if branch pr.feature-A is used in opened pull request then build will be triggered
Workflow example
temporary WIP branch shared between several developers: wip.feature-A, any commit to this branch will trigger the build
when branch is ready to be merged to master you can rename it from wip.feature-A to pr.feature-A and open pull request
if while reviewing pull request you want to apply new fixes, just push to pr.feature-A
On all the steps above only one build will be triggered.
For one of the repositories, I was working with, here is what I wanted:
There is an origin repo which is the main repo which does all the releases.
I wanted that all the pull requests coming to master branch of origin should be built with Travis only once irrespective of the fact that it comes from a forked repo or any other branch of the origin itself.
For this case, this works like a charm
if: (type == push) OR (type == pull_request AND fork == true)