Running GitHub Actions for Certain Commit Messages
ryangjchandler.co.uk
ryangjchandler.co.uk
jobs:
format:
runs-on: ubuntu-latest
if: "! contains(github.event.head_commit.message, 'wip')"Java people must have ptsd flashbacks
if: "! contains(github.event.head_commit.message, 'wip')"
is technically yaml, but in truth it's a completely different language with completely different grammar embedded in a yaml string. if pure yaml structure isn't good enough to fulfill use cases of the product, what's the point of using it? you now have a yaml parser and a whatever-this-is parser that needs to be invoked... sometimes, according to some yaml schema? why not create a proper grammar for the whole thing instead of only for a subset? as is, you have two problems: yaml and your custom language - i'd rather have one problem.On the other end, we now use Jenkins (the newer version), so every job is a huge Groovy script pretending to be a config file. Much steeper learning curve for anything simple.
Pick your poison.
You'd end up with config files that are actually readable (even to non-rubyists), with a shallow learning curve, but still easily extensible.
Here's a 5 minute mockup: https://gist.github.com/gkampjes/559ebe708343bb7c2f590c0065d...
Looks nicer than any .yaml file (or Groovy script) I've ever seen.
Regular expressions and SQL in my Python
JavaScript and CSS in my HTML
Sed / Awk / etc in my Bash
Embedding a custom conditional syntax in YAML feels pretty tame in comparison to those.
- Python provides a grammar for its implementation of regex (note that some langauges make regexes first-class syntax - perl, JS)
- JS has a defined standard cross-platform cross-browser syntax, ditto CSS (yes i know it's not 100% true)
- sed/awk in bash - i agree - but there's a bigger POSIX standard which defines all of it
the problem with yaml is that it isn't even a language, it's just a way to describe a recursive tree/list data structure. everybody defines their own language pretending to standardize on yaml where in fact the syntax similarities are doing little more than mislead you what product you're creating documents for.
On your examples, one mixes an specialized language into a general one. The general language is much better for most tasks, but once in a while there is a problem that fits the specialized one. But YAML isn't much better than a general language for defining data structures (what config files are), and isn't general in any way.
Honestly not sure why YAML is used so much. It either has stuff like this hacked in, or some templating structure, or both. Never the same between one CI tool and another, so you're always having to re-learn how to substitute an environment variable, or use some constructs provided by the tool itself.
And for any half-way complex pipeline, this YAML file will be a few thousand lines long, if not more, and basically impossible to follow.
But it's super confusing because ! usually means NOT in any programming context so you would mentally parse that as the message NOT containing "wip" when in reality, the opposite is what happens. CloudFormation does this too and they have "If" defined as a custom function so you end up with !If which is super confusing for a condition where you expect "if condition is true do this else that".
This isn’t a YAML tag; it’s just YAML embedding some opaque text from some random command-language that uses exclamation marks to mean something.
In fact, actually considering the meaning of the action, the ! used here probably is just the regular ol’ boolean NOT operator in most languages: the action has specified that it should trigger only for commits that aren’t tagged as WIPs. (Which is an eminently-sensible condition to provide.)
Which makes things even more confusing overall since ! is a thing in YAML when it's not wrapped in quotes.
Suddenly you have all of these tools implementing their idea of custom behavior in different ways.
jobs:
format:
runs-on: ubuntu-latest
if: |
! contains(github.event.head_commit.message, ‘wip’)
Other systems that output YAML (e.g. Kubernetes) always emit block literals for embedded user-supplied strings, reserving inline string literals for the cases where the string isn’t expected to need quoting — e.g. string-serialized enum option-values; symbol/atom/keyword-typed values; and sometimes URLs.I guess this applies to solo developers who mainly work out of master and like to compulsively push upstream to save their work. (Or am I wrong?)
if: "! contains(github.event.head_commit.message, '[skip ci]')"if: contains(github.event.pull_request.labels.*.name, 'wip')