git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2] ci: allow per-branch config for GitHub Actions

From
Jeff King <peff@peff.net>
Date
May 7, 2020, 16:20 UTC
Message-ID
<20200507162011.GA3638906@coredump.intra.peff.net>
In-Reply-To
<20200505210451.GA645290@coredump.intra.peff.net>
On Tue, May 05, 2020 at 05:04:51PM -0400, Jeff King wrote:
> Subject: [PATCH] ci: allow per-branch config for GitHub Actions
Here's a "v2" of that patch based on the discussion.

I think it smooths some of the rough edges of the orphan-branch approach, while still having a cost on par with other suggestions (or at least ones that truly allow any config; we can check for "for-ci/**" or something very cheaply, but that implies hard-coding it for everybody). I think the cost here is acceptable, and it gives us room to add more features in the future.

If Actions eventually adds per-repo variable storage that can be used in "if:" conditionals, then we could eventually switch to that. :)

The documentation here should be enough to let people work with it. But we'd probably want to take Danh's patch to mention Actions in SubmittingPatches on top (and it possibly could be modified to point to the ci/config directory).

-- >8 --
Subject: [PATCH] ci: allow per-branch config for GitHub Actions

Depending on the workflows of individual developers, it can either be convenient or annoying that our GitHub Actions CI jobs are run on every branch. As an example of annoying: if you carry many half-finished work-in-progress branches and rebase them frequently against master, you'd get tons of failure reports that aren't interesting (not to mention the wasted CPU).

This commit adds a new job which checks a special branch within the repository for CI config, and then runs a shell script it finds there to decide whether to skip the rest of the tests. The default will continue to run tests for all refs if that branch or script is missing.

There have been a few alternatives discussed:

One option is to carry information in the commit itself about whether it should be tested, either in the tree itself (changing the workflow YAML file) or in the commit message (a "[skip ci]" flag or similar). But these are frustrating and error-prone to use:

  - you have to manually apply them to each branch that you want to mark
  - it's easy for them to leak into other workflows, like emailing patches

We could likewise try to get some information from the branch name. But that leads to debates about whether the default should be "off" or "on", and overriding still ends up somewhat awkward. If we default to "on", you have to remember to name your branches appropriately to skip CI. And if "off", you end up having to contort your branch names or duplicate your pushes with an extra refspec.

By comparison, this commit's solution lets you specify your config once and forget about it, and all of the data is off in its own ref, where it can be changed by individual forks without touching the main tree.

There were a few design decisions that came out of on-list discussion. I'll summarize here:

 - we could use GitHub's API to retrieve the config ref, rather than a
   real checkout (and then just operate on it via some javascript). We
   still have to spin up a VM and contact GitHub over the network from
   it either way, so it ends up not being much faster. I opted to go
   with shell to keep things similar to our other tools (and really
   could implement allow-refs in any language you want). This also makes
   it easy to test your script locally, and to modify it within the
   context of a normal git.git tree.
 - we could keep the well-known refname out of refs/heads/ to avoid
   cluttering the branch namespace. But that makes it awkward to
   manipulate. By contrast, you can just "git checkout ci-config" to
   make changes.
 - we could assume the ci-config ref has nothing in it except config
   (i.e., a branch unrelated to the rest of git.git). But dealing with
   orphan branches is awkward. Instead, we'll do our best to efficiently
   check out only the ci/config directory using a shallow partial clone,
   which allows your ci-config branch to be just a normal branch, with
   your config changes on top.
 - we could provide a simpler interface, like a static list of ref
   patterns. But we can't get out of spinning up a whole VM anyway, so
   we might as well use that feature to make the config as flexible as
   possible. If we add more config, we should be able to reuse our
   partial-clone to set more outputs.
Signed-off-by: Jeff King <peff@peff.net>
---
 .github/workflows/main.yml  | 42 +++++++++++++++++++++++++++++++++++++
 ci/config/allow-refs.sample | 26 +++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100755 ci/config/allow-refs.sample
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index fd4df939b5..802a4bf7cd 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -6,7 +6,39 @@ env:
   DEVELOPER: 1
 
 jobs:
+  ci-config:
+      runs-on: ubuntu-latest
+      outputs:
+        enabled: ${{ steps.check-ref.outputs.enabled }}
+      steps:
+        - name: try to clone ci-config branch
+          continue-on-error: true
+          run: |
+            git -c protocol.version=2 clone \
+              --no-tags \
+              --single-branch \
+              -b ci-config \
+              --depth 1 \
+              --no-checkout \
+              --filter=blob:none \
+              https://github.com/${{ github.repository }} \
+              config-repo &&
+              cd config-repo &&
+              git checkout HEAD -- ci/config
+        - id: check-ref
+          name: check whether CI is enabled for ref
+          run: |
+            enabled=yes
+            if test -x config-repo/ci/config/allow-ref &&
+               ! config-repo/ci/config/allow-ref '${{ github.ref }}'
+            then
+              enabled=no
+            fi
+            echo "::set-output name=enabled::$enabled"
+
   windows-build:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
     runs-on: windows-latest
     steps:
     - uses: actions/checkout@v1
@@ -70,6 +102,8 @@ jobs:
         name: failed-tests-windows
         path: ${{env.FAILED_TEST_ARTIFACTS}}
   vs-build:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
     env:
       MSYSTEM: MINGW64
       NO_PERL: 1
@@ -154,6 +188,8 @@ jobs:
                           ${{matrix.nr}} 10 t[0-9]*.sh)
         "@
   regular:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
     strategy:
       matrix:
         vector:
@@ -189,6 +225,8 @@ jobs:
         name: failed-tests-${{matrix.vector.jobname}}
         path: ${{env.FAILED_TEST_ARTIFACTS}}
   dockerized:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
     strategy:
       matrix:
         vector:
@@ -213,6 +251,8 @@ jobs:
         name: failed-tests-${{matrix.vector.jobname}}
         path: ${{env.FAILED_TEST_ARTIFACTS}}
   static-analysis:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
     env:
       jobname: StaticAnalysis
     runs-on: ubuntu-latest
@@ -221,6 +261,8 @@ jobs:
     - run: ci/install-dependencies.sh
     - run: ci/run-static-analysis.sh
   documentation:
+    needs: ci-config
+    if: needs.ci-config.outputs.enabled == 'yes'
     env:
       jobname: Documentation
     runs-on: ubuntu-latest
diff --git a/ci/config/allow-refs.sample b/ci/config/allow-refs.sample
new file mode 100755
index 0000000000..f157f1945a
--- /dev/null
+++ b/ci/config/allow-refs.sample
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Sample script for enabling/disabling GitHub Actions CI runs on
+# particular refs. By default, CI is run for all branches pushed to
+# GitHub. You can override this by dropping the ".sample" from the script,
+# editing it, committing, and pushing the result to the "ci-config" branch of
+# your repository:
+#
+#   git checkout -b ci-config
+#   cp allow-refs.sample allow-refs
+#   $EDITOR allow-refs
+#   git commit -am "implement my ci preferences"
+#   git push
+#
+# This script will then be run when any refs are pushed to that repository. It
+# gets the fully qualified refname as the first argument, and should exit with
+# success only for refs for which you want to run CI.
+
+case "$1" in
+# allow one-off tests by pushing to "for-ci" or "for-ci/mybranch"
+refs/heads/for-ci*) true ;;
+# always build your integration branch
+refs/heads/my-integration-branch) true ;;
+# don't build any other branches or tags
+*) false ;;
+esac
-- 
2.26.2.1005.ge383644752
Previous: Junio C HamanoNext: Taylor Blau
Message 37 of 62 in “ci: respect the [skip ci] convention in our GitHub workflow "CI/PR"”
  1. ci: respect the [skip ci] convention in our GitHub workflow "CI/PR"Johannes Schindelin via GitGitGadget, May 2, 2020
  2. Jeff KingMay 3, 2020
  3. Danh DoanMay 3, 2020
  4. Jeff KingMay 4, 2020
  5. 0/2 Limit GitHub Actions to designated branchesĐoàn Trần Công Danh, May 4, 2020
  6. 1/2 CI: limit GitHub Actions to designated branchesĐoàn Trần Công Danh, May 4, 2020
  7. Jeff KingMay 4, 2020
  8. Taylor BlauMay 4, 2020
  9. Junio C HamanoMay 4, 2020
  10. Taylor BlauMay 4, 2020
  11. Jeff KingMay 4, 2020
  12. Junio C HamanoMay 5, 2020
  13. Jeff KingMay 4, 2020
  14. Taylor BlauMay 5, 2020
  15. Jeff KingMay 5, 2020
  16. Junio C HamanoMay 5, 2020
  17. Jeff KingMay 5, 2020
  18. Jeff KingMay 5, 2020
  19. Junio C HamanoMay 5, 2020
  20. Jeff KingMay 5, 2020
  21. Junio C HamanoMay 5, 2020
  22. Johannes SchindelinMay 6, 2020
  23. Junio C HamanoMay 6, 2020
  24. Jeff KingMay 7, 2020
  25. Jeff KingMay 7, 2020
  26. Junio C HamanoMay 7, 2020
  27. Đoàn Trần Công DanhMay 7, 2020
  28. Đoàn Trần Công DanhMay 7, 2020
  29. Đoàn Trần Công DanhMay 6, 2020
  30. Junio C HamanoMay 6, 2020
  31. Đoàn Trần Công DanhMay 6, 2020
  32. Junio C HamanoMay 6, 2020
  33. Jeff KingMay 7, 2020
  34. Junio C HamanoMay 7, 2020
  35. Jeff KingMay 7, 2020
  36. Junio C HamanoMay 7, 2020
  37. ci: allow per-branch config for GitHub ActionsJeff King, May 7, 2020
  38. Taylor BlauMay 7, 2020
  39. Jeff KingMay 7, 2020
  40. Junio C HamanoMay 7, 2020
  41. Jeff KingMay 7, 2020
  42. Junio C HamanoMay 7, 2020
  43. Jeff KingMay 8, 2020
  44. Đoàn Trần Công DanhMay 9, 2020
  45. Đoàn Trần Công DanhMay 5, 2020
  46. 2/2 SubmittingPatches: advertise GitHub Actions CIĐoàn Trần Công Danh, May 4, 2020
  47. Junio C HamanoMay 4, 2020
  48. Đoàn Trần Công DanhMay 5, 2020
  49. 0/3 Provide option to opt in/out GitHub ActionsĐoàn Trần Công Danh, May 5, 2020
  50. 1/3 SubmittingPatches: advertise GitHub Actions CIĐoàn Trần Công Danh, May 5, 2020
  51. Jeff KingMay 5, 2020
  52. Đoàn Trần Công DanhMay 5, 2020
  53. Jeff KingMay 5, 2020
  54. 2/3 CI: limit GitHub Actions to designated branchesĐoàn Trần Công Danh, May 5, 2020
  55. Jeff KingMay 5, 2020
  56. Đoàn Trần Công DanhMay 5, 2020
  57. Jeff KingMay 5, 2020
  58. Junio C HamanoMay 5, 2020
  59. 3/3 fixup! CI: limit GitHub Actions to designated branchesĐoàn Trần Công Danh, May 5, 2020
  60. Junio C HamanoMay 5, 2020
  61. Jeff KingMay 5, 2020
  62. Junio C HamanoMay 3, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.