[HN Gopher] I'll think twice before using GitHub Actions again
       ___________________________________________________________________
        
       I'll think twice before using GitHub Actions again
        
       Author : nemwiz
       Score  : 114 points
       Date   : 2025-01-20 03:41 UTC (19 hours ago)
        
 (HTM) web link (ninkovic.dev)
 (TXT) w3m dump (ninkovic.dev)
        
       | bramblerose wrote:
       | In the end, this is the age old "I built by thing on top of a 3rd
       | party platform, it doesn't quite match my use case (anymore) and
       | now I'm stuck".
       | 
       | Would GitLab have been better? Maybe. But chances are that there
       | is another edge case that is not handled well there. You're in a
       | PaaS world, don't expect the platform to adjust to your workflow;
       | adjust your workflow to the platform.
       | 
       | You could of course choose to "step down" (PaaS to IaaS) by just
       | having a "ci" script in your repo that is called by GA/other CI
       | tooling. That gives you immense flexibility but also you lose
       | specific features (e.g. pipeline display).
        
         | perlgeek wrote:
         | > Would GitLab have been better?
         | 
         | My impression of gitlab CI is that it's also not built for
         | monorepos.
         | 
         | (I'm a casual gitlab CI user).
        
           | dezgeg wrote:
           | I'm not sure if there's a monorepo vs polyrepo difference;
           | just that anything complex is pretty painful in gitlab. YAML
           | "programming" just doesn't scale.
        
         | Hamuko wrote:
         | Doesn't everything in GitLab go into a single pipeline? GitHub
         | at least makes splitting massive CI/CD setups easier by
         | allowing you to write them as separate workflows that are
         | separate files.
        
           | dezgeg wrote:
           | You can have pipelines trigger child pipelines in gitlab, but
           | usability of them is pretty bad, viewing logs/results of
           | those always needs extra clicking.
        
           | dijksterhuis wrote:
           | > GitHub at least makes splitting massive CI/CD setups easier
           | by allowing you to write them as separate workflows that are
           | separate files.
           | 
           | this makes me feel like you're really asking "can i split up
           | my gitlab CICD yaml file or does everything need to be in one
           | file".
           | 
           | if that's the case:
           | 
           | yes it does eventually all end up in a single pipeline
           | (ignoring child pipelines).
           | 
           | but you can split everything up and then use the `include`
           | statement to pull it all together in one main pipeline file
           | which makes dealing with massive amounts of yaml much easier.
           | 
           | https://docs.gitlab.com/ee/ci/yaml/includes.html
           | 
           | you can also use `include` to pull in a yaml config from
           | another project to add things like SAST on the fly.
           | 
           | previous workplace i had like 4 CICD template repos and
           | constructed all 30 odd actual build repos from those four
           | templates.
           | 
           | used `include` to pull in some yaml template jobs, which i
           | made run when by doing something like (it's been a while,
           | might get this wrong)                   include:
           | project: 'cicd/templates'           file: 'builds.yml'
           | stages:           - build              job_a:
           | stage: build           extends: .job_a_from_template
           | variables:             IMAGE_NAME: "myimage"
           | IMAGE_REPO: "somerepo.org"
           | 
           | this doesn't run anything for `job_b_from_template` ... you
           | just end up defining the things you want to run for each
           | case, plus any variables you need to provide / override.
           | 
           | you can also override stuff like rules on when it should run
           | if you want to. which is handy.
           | 
           | gitlab CICD can be really modular when you get into it.
           | 
           | if that wasn't the case: on me.
           | 
           | edit: switched to some yaml instead of text which may or may
           | not be wrong. dunno. i have yet to drink coffee.
        
             | dijksterhuis wrote:
             | addendum you can also do something like this, which means
             | you don't have to redefine every job in your main ci file,
             | just define _the ones you don't want to run_
             | include:           project: 'cicd/templates'
             | file: 'builds.yml'              variables:
             | IMAGE_NAME: something           IMAGE_REPO: some.org
             | job_b:           rules:             - when: never
             | 
             | where the template you import has a job_a and job_b
             | definition. both get pulled in, but job_b gets overwritten
             | so it never runs.
             | 
             | less useful when just splitting things into multiple files
             | to make life simpler.
             | 
             | super useful when using the same templates across multiple
             | independent repositories to make everything build in as
             | close to the same way as possible.
        
       | tevon wrote:
       | I call writing GitHub Actions "Search and Deploy", constantly
       | pushing to a branch to get an action to run is a terrible
       | pattern...
       | 
       | You'd think, especially with the deep VS Code integration, they'd
       | have at least a basic sanity-check locally, even if not running
       | the full pipeline.
        
         | 8n4vidtmkvmk wrote:
         | Not just me then? I was trying to fix a GitHub action just
         | today but I have no clue how I'm supposed to tear it, so I just
         | keep making tiny changes and pushing.... Not a good system but
         | I'm still within the free tier so I'm willing to put up with it
         | I guess.
        
           | masklinn wrote:
           | I think it's everyone, debugging GH actions is absolute hell,
           | and it gets terrifying when the action interacts with the
           | world (e.g. creating and deploying packages to a registry).
        
             | oefrha wrote:
             | > it gets terrifying when the action interacts with the
             | world (e.g. creating and deploying packages to a registry).
             | 
             | To be fair, testing actions with side effects on the wider
             | world is terrifying even if you're running it locally,
             | maybe more so because your nonstandard local environment
             | may have surprises (e.g. an env var you set then forgot)
             | while the remote environment mostly only has stuff you
             | set/installed explicitly, and you can be sloppier (e.g.
             | accidentally running ./deploy when you wanted to run
             | ./test). That part isn't a GH Actions problem.
        
           | arccy wrote:
           | git commit --allow-empty -m "bump ci"
           | 
           | unless your pipeline does magic with trying to detect changed
           | files
        
         | nunez wrote:
         | Biggest pet peeve of GHA by a country mile.
        
         | pavon wrote:
         | Ah yes, I have a git alias created specifically for the "we
         | don't know what it does until we push it" world of CI:
         | 
         | > yolo = "!git commit --all --amend --no-edit && git push
         | --force #"
        
       | androa wrote:
       | GitHub (Actions) is simply not built to support monorepos. Square
       | peg in a round hole and all that. We've opted for using `meta` to
       | simulate monorepos, while being able to use GitHub Actions
       | without too much downsides.
        
         | Imustaskforhelp wrote:
         | hey could you please share the`meta` tool you mentioned ,
         | sounds interesting ! couldn't find it on internet [skill issue]
        
           | joshka wrote:
           | Guessing it's https://github.com/mateodelnorte/meta googlefu
           | "meta github repo"
        
             | Imustaskforhelp wrote:
             | hey thanks!
             | 
             | definitely interesting!
             | 
             | I do wonder if this _really_ solves the author problem
             | because by the looks of it , you just have to run meta
             | command and it would run over each of the sub directory.
             | While at the same time , I think I like it because this is
             | what I think people refer to as  "modular monolith"
             | 
             | Combining this with nats https://nats.io/ (hey if you don't
             | want it to be over the network , you could use nats with
             | the memory model of your application itself to reduce any
             | overhead) and essentially just get yourself a really
             | modular monolith in which you can then seperate things
             | selectively (ahem , microservices) afterwards rather
             | easily.
        
               | HumanOstrich wrote:
               | Modular monolith refers to the architecture of your
               | application[1]. It's a different concept from "monorepo",
               | although they can be used together.
               | 
               | I'm not sure what NATS has to do with anything in this
               | post or discussion. Also, a modular monolith is almost
               | the antithesis of microservices.
               | 
               | [1]: https://www.thoughtworks.com/en-
               | us/insights/blog/microservic...
        
       | arghwhat wrote:
       | > no way of running actions locally
       | 
       | My policy is to never let pipeline DSLs contain any actual logic
       | outside orchestration for the task, relying solely on one-liner
       | build or test commands. If the task is more complicated than a
       | one-liner, make a script for it in the repo to make it a one-
       | liner. Doesn't matter if it's GitHub Actions, Jenkins, Azure
       | DevOps (which has super cursed yaml), etc.
       | 
       | This in turn means that you can do what the pipeline does with a
       | one-liner too, whether manually, from a vscode launch command, a
       | git hook, etc.
       | 
       | This same approach can fix the mess of path-specific validation
       | too - write a regular script (shell, python, JS, whatever you
       | fancy) that checks what has changed and calls the appropriate
       | validation script. The GitHub action is only used to run the
       | script on PR and to prepare the CI container for whatever the
       | script needs, and the same pipeline will always run.
        
         | Tainnor wrote:
         | The reason why many CI configs devolve into such a mess isn't
         | typically that they don't extract complicated logic into
         | scripts, it's about all the interactions with the CI system
         | itself. This includes caching, sharing of artifacts, generating
         | reports, configuring permissions, ordering of jobs, deciding
         | when which jobs will run, deciding what to do when jobs fail,
         | etc. All of this can get quite messy in a large enough project.
        
           | pydry wrote:
           | It never becomes unbearably messy this way though.
           | 
           | The reason it gets unbearably messy is because most people
           | google "how to do x in github actions" (e.g. send a slack
           | message) and there _is_ a way and it 's almost always worse
           | than scripting it yourself.
        
         | izietto wrote:
         | This. I'd go more relaxed on the one-liner requirement, a few
         | lines are fine, but the approach is correct IMHO.
        
         | jicea wrote:
         | I don't understand why this is not the evident approach for
         | everyone writing GitHub Actions/GitLab CI/CD yaml etc....
         | 
         | I've struggled in some teams to explained why it's better to
         | extract your command in scripts (ShellCheck on it, scripts are
         | simple to run locally etc...) instead of writing a Frankenstein
         | of YAML and shell commands. I hope someday to find an
         | authoritative guidelines on writing pipeline that promote this
         | approach so at least I can point to this link instead of
         | defending myself being a dinosaur!
        
           | arghwhat wrote:
           | My "favorite" is when I see people go all in, writing
           | thousands of lines of Jenkins-flavor Groovy that parses JSON
           | build specifications of arbitrary complexity to sort out how
           | to build that particular project.
           | 
           | "But then we can reuse the same pipeline for all our
           | projects!"
        
             | lowercased wrote:
             | I can rarely reuse the same pipeline for the same project 6
             | months down the road, much less reuse for anything else.
             | 
             | The few bits that end up getting reused are the
             | externalized bash scripts.
        
             | ozim wrote:
             | I think that is pitfall of software devs.
             | 
             | For me it was an epiphany as software dev - not to write
             | reusable extensible scripts - I am so much more productive
             | after that.
        
           | mrweasel wrote:
           | In a previous job we had a team tasked with designing these
           | "modern" CI/CD pipeline solutions, mostly meant for
           | Kubernetes, but it was suppose to work for everything. They
           | had such a hard on for tools that would run each step as a
           | separate isolated task and did not want pipelines to
           | "devolve" into shell scripts.
           | 
           | Getting anything done in such environments are just a pain.
           | You spend more time fighting the systems than you do actually
           | solving problems. It is my opinion that a CI/CD system needs
           | just the following features: Triggers (source code repo, http
           | endpoints or manually triggered), secret management and shell
           | script execution. That's it, you can build anything using
           | that.
        
             | eddd-ddde wrote:
             | I think what they really wanted was something like bazel.
             | The only real benefit I can think right now for not
             | "devolving" into shell scripts is distributed caching with
             | hermetic builds. It has very real benefits but it also
             | requires real effort to work correctly.
        
             | datavirtue wrote:
             | I just joined as the enterprise architect for company that
             | has never had one. There is an existing devops team that is
             | making everyone pull their hair out and I haven't had a
             | single spare minute to dig in on their mess but this sounds
             | early familiar.
        
           | maccard wrote:
           | To make the thing actually fast at scale, a lot of the logic
           | ends up being specific to the provider; requiring tokens,
           | artifacts etc that aren't available locally. You end up with
           | something that tries to detect if you're running locally or
           | in CI, and then you end up in exactly the same situation.
        
           | arccy wrote:
           | it can be quite hard to write proper scripts that work
           | consistently... different shells have different behaviours,
           | availability of local tools, paths, etc
           | 
           | and it feels like fighting against the flow when you're
           | trying to make it reusable across many repos
        
             | akdev1l wrote:
             | Containerize the build environment so everything is
             | captured (dependencies, build tools, etc)
        
               | carlmr wrote:
               | If you're not containerizing your CI/CD, you're really
               | lost.
        
               | darthwalsh wrote:
               | I'm not sold on using containers for macOS desktop
               | apps...
        
         | alkonaut wrote:
         | That's usually very hard or impossible for many things. The
         | AzDo yaml consists of a lot of steps that are specific to the
         | CI environment (fetching secrets, running tests on multiple
         | nodes, storing artifacts of various kinds).
         | 
         | Even if the "meat" of the script is a single build.ps oneliner,
         | I quickly end up with 200 line yaml scripts which have no
         | chance of working locally.
        
           | arghwhat wrote:
           | Azure DevOps specifically has a very broken approach to YAML
           | pipelines, because they effectively took their old graphical
           | pipeline builder and just made a YAML representation of it.
           | 
           | The trick to working with this is that you _don 't_ need any
           | of their custom Azure DevOps task types, and can use the
           | shell type (which has a convenient shorthand) just as well as
           | in any other CI environment. Even the installer tasks are
           | redundant - in other CI systems, you either use a container
           | image with what you need, or install stuff at the start, and
           | Azure DevOps works with both of these strategies.
           | 
           | So no, it's neither hard nor impossible, but Microsoft's
           | half-assed approach to maintaining Azure DevOps and overall
           | overcomplicated legacy design makes it a bit hard to realize
           | that doing what their documentation suggests is a bad idea,
           | and that you can use it in a modern way just fine. At least
           | their docs do not recommend that you use the dedicated NPM-
           | type task for `npm install` anymore...
           | 
           | (I could rant for ages about Azure DevOps and how broken and
           | unloved it is from Microsoft's side. From what I can tell,
           | they're just putting in the minimum effort to keep old
           | Enterprise customers that have been there through every
           | rename since Team Foundation Server from jumping ship - maybe
           | just until Github's enterprise side has matured enough? Azure
           | DevOps doesn't even integrate well with Azure, despite its
           | name!)
        
         | potamic wrote:
         | This is the right way to use CI/CD systems, as dumb
         | orchestrators without inherent knowledge of your software
         | stack. But the problem is, everything from their documentation,
         | templates, marketplace encourage you to do exactly the opposite
         | and couple your build tightly with their system. It's poor
         | product design imo, clearly optimising for vendor lock-in over
         | usability.
        
         | riperoni wrote:
         | I agree with wrapping things like build scripts to test
         | locally.
         | 
         | Still, some actions or CI steps are also not meant to be run
         | locally. Like when it publishes to a repo or needs any
         | credentials that are used by more than one person.
         | 
         | Btw, Github actions and corresponding YAML are derived from
         | Azure DevOps and are just as cursed.
         | 
         | The whole concept of Github CI is just pure misuse of
         | containers when you need huge VM images - container is
         | technically correct, but a far fetched word for this - that
         | have all kinds of preinstalled garbage to run typescript-
         | wrapped code to call shell scripts.
        
         | nunez wrote:
         | While youre correct, environmental considerations are another
         | advantage that testing locally SHOULD be able to provide (i.e.
         | you can test your scripts or Make targets or whatever in the
         | same runner that runs in the actual build system.)
         | 
         | This is not possible with GHA.
        
           | arghwhat wrote:
           | Of course you can, just specify a container image of your
           | choice and run the same container for testing locally.
           | 
           | However, replicating environmental details is only relevant
           | where the details are known to matter. A lot of effort has
           | been wasted and workflows crippled by the idea that
           | _everything_ must be 100% identical irrespective of actual
           | dependencies and real effects.
        
         | hinkley wrote:
         | I'll go so far as to say the massive add on/plugin list and
         | featuritis of CI/CD tools is actively harmful to the sanity of
         | your team.
         | 
         | The only functionality a CI tool should be providing is:
         | 
         | - starting and running an environment to build shit in
         | 
         | - accurately tracking success or failure
         | 
         | - accurate association of builds with artifacts
         | 
         | - telemetry (either their own or integration) and audit trails
         | 
         | - correlation with project planning software
         | 
         | - scheduled builds
         | 
         | - build chaining
         | 
         | That's a lot, but it's a lot less than any CI tool made in the
         | last 15 years does, and that's enough.
         | 
         | There's a big difference for instance between having a tool
         | that understands Maven information enough to present a build
         | summary, and one with a Maven fetch/push task. The latter is a
         | black box you can't test locally, and your lead devs can't
         | either, so when it breaks, it triggers helplessness.
         | 
         | If the only answer to a build failure is to stare at config and
         | wait for enlightenment, you fucked up.
        
         | no_wizard wrote:
         | Folks pick the wrong tool for the job at hand.
         | 
         | I suspect the author of the article could greatly simplify
         | matters if they used a task running tool to orchestrate running
         | tasks, for example. Pick whatever manner of decoupling you want
         | really, most of the time this is the path to simplified CI
         | actions. CI is best when its thought of as a way to stand up
         | fresh copies of an environment to run things inside of.
         | 
         | I have never had the struggles that so many have had with CI as
         | a result. Frankly, I'm consistently surprised at how overly
         | complex people make their CI configurations. There's better
         | tools for orchestration and dependency dependent builds, which
         | is not its purpose to begin with.
        
           | ledauphin wrote:
           | I generally agree with you, but I'd be interested to hear
           | your take on what the purpose of CI _actually is_.
           | 
           | It seems to me that a big part of the problem here (which I
           | have also seen/experienced) is that there's no one specific
           | thing that something like GitHub Actions is uniquely suited
           | for. Instead, people want "a bunch of stuff to happen" when
           | somebody pushes a commit, and they imagine that the best way
           | to trigger all of that is to have an incredibly complex - and
           | also bespoke - system on the other end that does all of it.
           | 
           | It's like we learned the importance of modularity in the the
           | realm of software design, but never applied what we learned
           | to the tools that we work with.
        
         | ukoki wrote:
         | > My policy is to never let pipeline DSLs contain any actual
         | logic outside orchestration for the task,
         | 
         | I call this "isomorphic CI" -- ie: as long as you set the
         | correct env vars, it should run identically on GitHub actions,
         | Jenkins, your local machine, a VM etc
        
           | reactordev wrote:
           | This is the only DevOps way. Abstract the build into a single
           | step.
        
             | vvillena wrote:
             | And yet, you would be surprised at the amount of people who
             | react like that's an ignorant statement ("not feasible in
             | real world conditions"), an utopic goal ("too much time to
             | implement"), an impossible feat ("automation difficults
             | human oversight"), or, my favorite, the "this is beneath
             | us" excuse ("see, we are special and this wouldn't work
             | here").
             | 
             | Automation renders knowledge into a set of executable
             | steps, which is much better than rendering knowledge into
             | documentation, or leaving it to rot in people's minds.
             | Compiling all rendered knowledge into a single step is the
             | easiest way to ensure all elements around the build and
             | deployment lifecycle work in unison and are guarded around
             | failures.
        
         | InvertedRhodium wrote:
         | I use gitlab-ci-local to run Gitlab pipelines locally - does
         | such a thing not exist for GitHub actions?
        
         | 0xbadcafebee wrote:
         | 100%. The ci/cd job should be nothing more than a wrapper
         | around the actual logic which is code in your repo.
         | 
         | I write a script called `deploy.sh` which is my wrapper for my
         | ci/cd jobs. It takes options and uses those options to find the
         | piece of code to run.
         | 
         | The ci/cd job can be parameterized or matrixed. The eventually-
         | run individual jobs have arguments, and those are passed to
         | deploy.sh. Secrets/environment variables are set from the ci/cd
         | system, also parameterized/matrixed (or alternately, a self-
         | hosted runner can provide deploy.sh access to a vault).
         | 
         | End result: from my laptop I can run `deploy.sh deploy --env
         | test --modules webserver` to deploy the webserver to _test_ ,
         | and the CI/CD job also runs the same job the same way. The only
         | thing I maintain that's CI/CD-specific is the GitHub Action-
         | specific logic of how to get ready to run `deploy.sh`, which I
         | write once and never change. Thus I could use 20 different
         | CI/CD systems, but never have to refactor my actual deployment
         | code, which also always works on my laptop. Vendor lock-in is
         | impossible, thanks to a little abstraction.
         | 
         | (If you have ever worked with a team with 1,000 Jenkins jobs
         | and the team has basically decided they can never move off of
         | Jenkins because it would take too much work to rewrite all the
         | jobs, you'll understand why I do it this way)
        
       | vrnvu wrote:
       | > GitHub doesn't care
       | 
       | GitHub cares. GitHub cares about active users on their platform.
       | Whether it's managing PRs, doing code reviews, or checking the
       | logs of another failed action.
        
         | joshka wrote:
         | GitHub often actively doesn't act in situations where acting
         | would be prudent, which portrays from an outside perspective a
         | disinterest in those who give their time to document
         | shortcomings. Would you care to guess when the last time that
         | the GitHub API was updated? It's probably much longer than
         | you'd think (2+ years at this point).
        
         | presentation wrote:
         | They don't care about things that I care about, including
         | everything the author talked about, and also things like
         | allowing whitespace-ignore on diffs to be set on by default in
         | a repo or per user - an issue that's been open for half a
         | decade now.
         | 
         | (Whitespace is just noise in a typescript repo with automatic
         | formatting)
         | 
         | https://github.com/orgs/community/discussions/5486
        
       | makingstuffs wrote:
       | Not sure if I am missing something but you can definitely run
       | (some?) GH actions locally with act:
       | https://github.com/nektos/act
       | 
       | Seen a couple posts on here say otherwise.
        
         | joshdavham wrote:
         | He mentioned act in the article.
        
         | alhadrad wrote:
         | Act has limitations because GitHub Actions run via
         | virtualization, while Act runs via containerization. This means
         | that actions behave differently across the two platforms.
        
       | flohofwoe wrote:
       | IMHO the main problem with GH Actions is that the runners are so
       | slow. Feels like running your build on a frigging C64 sometimes
       | ;)
        
         | Hamuko wrote:
         | Are you hosting your own runners or relying on GitHub's?
        
         | ramon156 wrote:
         | Blacksmith is your buddy. Its free and just has better images
         | for single-core operations. Unless you're Google, I can
         | guarantee it's faster.
        
       | joshdavham wrote:
       | > It's a known thing that there is no way of running GitHub
       | Actions locally. There is a tool called act but in my experience
       | it's subpar.
       | 
       | I really hope there will be a nice, official tool to run gh
       | actions locally in the future. That would be incredible.
        
       | benrutter wrote:
       | Oh boy, there's a special kind of hell I enter into everytime I
       | set up new github actions. I wrote a blog post a few months ago
       | about my pain[0] but one of the main things I've found over the
       | years is you can massively reduce how horrible writing github
       | actions is by _avoiding_ prebuilt actions, and just using it as a
       | handy shell runner.
       | 
       | If you write behaviour in python/ruby/bash/hell-rust-if-you-
       | really-want and leave your github action at `run: python
       | some/script.py` then you'll have something that's _much_ easy to
       | test locally, and save yourself a lot of pain, even if you wind
       | up with slightly more boilerplate.
       | 
       | [0] https://benrutter.github.io/posts/github-actions/
        
         | Imustaskforhelp wrote:
         | theoretically we could also use https://just.systems/ or
         | https://mise.jdx.dev/ instead of directly calling gh actions
         | but I haven't tried gh actions personally yet , If its really
         | the nightmare you are saying , then that's sad.
        
         | riperoni wrote:
         | At this point, just pause with Github Actions and compare it to
         | how GiLab handles CI.
         | 
         | Much more intuitive, taking shell scripts and other script
         | commands natively and not devolving into a mess of obfuscated
         | typescript wrapped actions that need a shit ton of
         | dependencies.
        
           | danillonunes wrote:
           | But you can do the same with GitHub, right? Although most
           | docs and articles focus on 3rd party actions, nothing stops
           | you to just run everything in your own shell script.
        
             | lolinder wrote:
             | Yes, you can, and we do at my current job. Much of the time
             | it's not even really the harder approach compared to using
             | someone else's action, it's just that the existence of
             | third party actions makes people feel obliged to use them
             | because they wouldn't want to be accused of Not Invented
             | Here Syndrome.
        
           | arccy wrote:
           | if anything, gitlab's ci seems even worse...
        
           | Aeolun wrote:
           | The problem with Gitlab CI is that now you need to use
           | Gitlab.
           | 
           | I'm not even sure when I started feeling like that was a bad
           | thing. Probably when they started glueing a bunch of badly
           | executed security crud onto the main product.
        
             | Espressosaurus wrote:
             | GitLab can't even show you more than a few lines of context
             | without requiring you to manually click a bunch of times.
             | Forget the CI functionality, for pull requests it's
             | absolutely awful.
        
       | kjuulh wrote:
       | I am biased because I built the rust SDK for dagger. But I think
       | it is a real step forward for CI. Is it perfect? Nope. But it
       | allows fixing a lot of the shortcomings the author has.
       | 
       | Pros:
       | 
       | - pipeline as code, write it as golang, python, typescript or a
       | mix of thr above.
       | 
       | - Really fast once cached
       | 
       | - Use your languages library for code sharing, versioning and
       | testing
       | 
       | - Runs everywhere local, ci etc. Easy to change from github
       | actions to something else.
       | 
       | Cons:
       | 
       | - Slow on the first run. Lots of pulling of docker images
       | 
       | - The DSL and modules can feel foreign initially.
       | 
       | - Modules are definitely a framework, I prefer just building
       | having a binary I can ship (which is why the rust SDK doesnt
       | support modules yet).
       | 
       | - Doesn't handle large mono repos well, it relies heavily on
       | caching and currently runs on a single node. It can work if you
       | don't have 100 of services especially if the builder is a large
       | machine.
       | 
       | Just the fact that you can actually write ci pipelines that can
       | be tested, packaged, versioned etc. Allows us to ship our
       | pipelines as products which is quite nice and something we've
       | come to rely on heavily
        
         | electromech wrote:
         | I'm genuinely intrigued by Dagger, but also super confused. For
         | example, this feels like extra complexity around a simple shell
         | command, and I'm trying to grok why the complexity is worth it:
         | https://docs.dagger.io/quickstart/test/#inspect-the-dagger-f...
         | 
         | I'm a fanboy of Rust, Containerization, and everything-as-code,
         | so on paper Dagger and your Rust SDK seems like it's made for
         | me. But when I read the examples... I dunno, I just don't get
         | it.
        
       | bitliner2 wrote:
       | Welcome to the jungle.
       | 
       | https://medium.com/@bitliner/why-gitlab-can-be-a-pain-ae1aa6...
       | 
       | I think it's not only GitHub.
       | 
       | Ideally we should handle it as any other code, that is: do tests,
       | handle multiple environments including the local environment,
       | lint/build time error detection etc
        
         | benrutter wrote:
         | Unhappy to confirm that for any poor souls using Azure DevOps,
         | it's even worse.
        
       | rednafi wrote:
       | You can't run AWS lambda or DyanmoDB locally too (well you can
       | but it's a hassle). So by that logic, we shouldn't use them at
       | all. I don't like working with CI too but I'll take GitHub
       | Actions over Jenkins/CircleCI/TravisCI any day.
        
         | chriswarbo wrote:
         | > You can't run AWS lambda or DyanmoDB locally too (well you
         | can but it's a hassle). So by that logic, we shouldn't use them
         | at all.
         | 
         | No, applying the logic to something like Lambda would mean
         | implementing handlers like:                   function
         | handle(lambdaRequest, lambdaContext) {           return
         | myFunction(
         | stuffExtractedFromLambdaRequest(lambdaRequest),
         | stuffExtractedFromLambdaContext(lambdaContext)           );
         | }
         | 
         | Then there's no need to go through the hassle of running Lambda
         | functions locally; since we can just run `myFunction` locally
         | instead.
         | 
         | Dynamo isn't the same, since it's just a service/API that we
         | call; we don't implement its logic, like we do for CI tasks,
         | Lambda functions, etc.
         | 
         | Whilst you're right that it's a hassle to run DynamoDB locally
         | (although not too bad, in my experience); that's also not
         | necessary. It's fine to run code locally which talks to a
         | remote DynamoDB; just set up the credentials appropriately.
        
           | rednafi wrote:
           | Yeah, and that doesn't stop us from using either of them.
           | What I tried to convey is that GHA isn't ideal and it has a
           | few warts but it's still better than most of the options
           | available out there.
        
         | sunshowers wrote:
         | The problem with the analogy is that GHA's interface is quite
         | thick.
        
         | arccy wrote:
         | lambda: https://docs.aws.amazon.com/serverless-application-
         | model/lat...
         | 
         | dynamodb:
         | https://docs.aws.amazon.com/amazondynamodb/latest/developerg...
         | 
         | doesn't seem any harder than running any other db
        
       | alkonaut wrote:
       | That GH Actions and Azure Pipelines both settled for this cursed
       | Yaml is hard to understand. Just make a real programming language
       | do it! And ffs make a local test env so I can run the thing.
        
       | bhaney wrote:
       | Article title: "[Common thing] doesn't work very well!"
       | 
       | Article body: "So we use a monorepo and-"
       | 
       | Tale as old as time
        
         | rasso wrote:
         | I'm also struggling with gh actions. And none of my repos is a
         | monorepo.
        
       | aa-jv wrote:
       | I use Github Actions as a fertile testing playground to work out
       | how to do things locally.
       | 
       | For example, if you've ever had to wade into the
       | codesigning/notarization quagmire, observing the methods projects
       | use with Github Actions to do it, can teach you a lot about how
       | to do things, locally.
        
       | pshirshov wrote:
       | > Jenkins, TeamCity
       | 
       | Yeah-yeah, but it's not like they allow you to run your build
       | definitions locally nor they address some other concerns. With
       | GHA you may use nix-quick-install in a declarative manner, nixify
       | your builds and then easily run them locally and under GHA. In
       | case of jenkins/tc you would have to jump through much more
       | hoops.
        
       | rickette wrote:
       | Every CI system has its flaws but GitHub Actions in my opinion is
       | pretty nice especially in terms of productivity; easy to setup,
       | tons of prebuild actions, lots of examples, etc.
       | 
       | I've used Tekton, Jenkins, Travis, Hudson, StarTeam, Rational
       | Jazz, Continuum and a host of other CI systems over the years but
       | GitHub Actions ain't bad.
        
       | angoragoats wrote:
       | Why is this team sticking multiple directories that are
       | "independent of each other" into a single repository? This sounds
       | like a clear case of doing version control wrong. Monorepos come
       | with their own set of challenges, and I don't think there are
       | many situations where they're actually warranted. They certainly
       | don't help for completely independent projects.
        
         | cbare wrote:
         | Yeah, sounds like the problems are more due to monorepos rather
         | than with GitHub actions. Seems like the pendulum always swings
         | too far. Overdoing microservices results in redundant code and
         | interservice spaghetti. Monorepos have their own set of issues.
         | The only solution is to think carefully about a what size chunk
         | of functionality you want to build, test, and deploy as a unit.
        
       | nunez wrote:
       | Posts like this make me miss Travis. Travis CI was incredible,
       | especially for testing CI locally. (I agree with the author that
       | act is a well done hack. I've stopped using it because of how
       | often I'd have something pass in act and fail in GHA.)
       | 
       | > GitHub doesn't care
       | 
       | My take: GitHub only built Actions to compete against GitLab CI,
       | as built-in CI was taking large chunks of market share from them
       | in the enterprise.
        
         | sureIy wrote:
         | To be fair, GitHub also charges for Actions minutes and
         | storage, so it's one of the few pieces that do generate
         | revenue.
        
       | xinayder wrote:
       | I tried to use GitHub Actions on Forgejo and... It's so much
       | worse than using an actual CI pipeline.
       | 
       | With Woodpecker/Jenkins you know exactly what your pipeline is
       | doing. With GitHub actions, not even the developers of the
       | actions themselves know what the runner does.
        
         | lolinder wrote:
         | > use GitHub Actions on Forgejo
         | 
         | What does this even mean? Are you talking about Forgejo
         | Actions, or are you somehow hosting your code on a Forgejo
         | instance but running CI through GitHub?
         | 
         | > With Woodpecker/Jenkins you know exactly what your pipeline
         | is doing.
         | 
         | If you wrote it from the ground up, sure. On the other hand,
         | I've inherited Jenkins pipelines that were written years before
         | I got there and involved three to four different plugins, and
         | they're _way_ worse to work with than the GitHub Actions that I
         | inherited.
        
         | myaccountonhn wrote:
         | Best one I've used is the CI of sourcehut. So simple and so
         | damn easy to set up.
        
           | gabeio wrote:
           | You basically achieve the same result on github actions if
           | you just ignore all of the github action yaml "magic"
           | settings in the syntax and let your makefile/script do the
           | logic which also makes it trivial to debug locally. But
           | upvote because I do love sourcehut, it's just so clean!
        
       | OptionOfT wrote:
       | So the way I've solved the multiple folders with independent
       | checks is like this:                   all-done:           name:
       | All done           # this is the job that should be marked as
       | required on GitHub. It's the only one that'll reliably trigger
       | # when any upstream fails: success           # when all upstream
       | skips: pass           # when all upstream success: success
       | # combination of upstream skip and success: success
       | runs-on: ubuntu-latest           needs:             - calculate-
       | version             - cargo-build             - cargo-fmt
       | - cargo-clippy-and-report             - cargo-test-and-report
       | - docker-build             - docker-publish           if: |
       | always()           steps:             - name: Fail!
       | shell: bash               if: |
       | contains(needs.*.result, 'failure') ||
       | contains(needs.*.result, 'cancelled')               run: |
       | echo "One / more upstream failed or was cancelled. Failing
       | job..."                        exit 1                    - name:
       | Success!               shell: bash               run: |
       | echo "Great success!"
       | 
       | That way it is resilient against checks not running because
       | they're not needed, but it still fails when any upstream actually
       | fails.
       | 
       | Now, I did end up running the tests of the front-end and back-end
       | because they upload coverage, and if my coverage tool doesn't get
       | both, it'll consider it as a drop in coverage and fail its check.
       | 
       | But in general, I agree with the writer of the post that it all
       | feels like it's not getting enough love.
       | 
       | For example, there is no support for yaml anchors, which really
       | hampers reusability on things that cannot be extracted to
       | separate flows (not to mention separate flows can only be nested
       | 4 deep).
       | 
       | There is also the issue that any commit made by GitHub actions
       | doesn't trigger another build. This is understandable, as you
       | want to avoid endless builds, but sometimes it's needed, and then
       | you need to do the ugly workaround with a PAT (and I believe it
       | can't even be a fine-grained one). Combine that with policies
       | that set a maximum time limit on tokens, your build becomes
       | brittle, as now you need to chase down the person with admin
       | access.
       | 
       | Then there is the issue of Docker actions. They tell you to pin
       | the action to an sha to prevent replacements. Except the action
       | itself points to a replaceable tag.
       | 
       | Lastly, there is a bug where when you create a report for your
       | action, you cannot specify the parent it belongs to. So your
       | ESLint report could be made a child of your coverage report.
        
       | keybored wrote:
       | Why is this so difficult?
       | 
       | 1. We apparently don't even have a name for it. We just call it
       | "CI" because that's the adjacent practice. "Oh no the CI failed"
       | 
       | 2. It's conceptually a program that reports failure if whatever
       | it is running fails and... that's it
       | 
       | 3. The long-standing principle of running "the CI" _after_
       | merging is so backwards that that-other Hoare disparagingly
       | called the correct way (guard "main" with a bot) for The Not
       | Rocket Science Principle or something. And that smug blog title
       | is still used to this day (or "what bors does")
       | 
       | 4. It's supposed to be configured declaratively but in the most
       | gross way that "declarative" has ever seen
       | 
       | 5. In the true spirit of centralization "value add": the local
       | option of (2) (report failure if failed) has to be hard or at the
       | very least inconvenient to set up
       | 
       | I'm not outraged when someone doesn't "run CI".
        
       | spzb wrote:
       | My recent experience with Github Actions is that it will randomly
       | fail running a pipeline that hasn't changed with an
       | incomprehensible error message. I re-run the action a few hours
       | later and it works perfectly.
        
       | forty wrote:
       | For the first point, some mono repo orchestrators (I'm thinking
       | of at least pnpm) have a way to do : run all the (for example)
       | tests for all the packages that had change from master branch +
       | all packages that depend transitively from those packages.
       | 
       | It's very convenient and avoid having to mess with the CI
       | limitations on the matter
        
       | baobun wrote:
       | GitHub Actions supporting yaml anchors would resolve one of the
       | gripes, which I share.
       | 
       | https://github.com/actions/runner/issues/1182
        
       | zxor wrote:
       | > The problem is that this step will only run when I change
       | something in the web-app1 folder. So if my pull request only made
       | changes in api1 I will never be able to merge my pull request!
       | 
       | This just seems like a bad implementation to me?
       | 
       | There are definitely ways to set up your actions so that they run
       | all of the unit tests without changes if you'd like, or so that
       | api1's unit tests are not required for a web-app1 related PR to
       | be merged.
        
         | hightrix wrote:
         | Absolutely correct. When creating a new workflow, I always
         | disable push/pull_request triggered builds and instead use the
         | manually triggered `workflow_dispatch` method. This makes
         | testing a new workflow much easier.
         | 
         | Additionally, you can use conditionals based on inputs in the
         | `workflow_dispatch` meaning that you could easily setup a "skip
         | api tests" or "include web tests" option.
        
       | SamuelAdams wrote:
       | > Our code sits in a monorepo which is further divided into
       | folders. Every folder is independent of each other and can be
       | tested, built, and deployed separately.
       | 
       | If this is true, and you still have problems running specific
       | Actions, why not break this into separate repositories?
        
       | ashishb wrote:
       | There are a lot of subtle pitfalls as well. Like no default
       | timeouts, excess permissions etc.
       | 
       | I wrote about it in detail https://ashishb.net/tech/common-
       | pitfalls-of-github-actions/ And even created a tool to generate
       | good configs GitHub.com/ashishb/gabo
        
       | spooneybarger wrote:
       | A lot of folks in this thread are focusing on the monorepo aspect
       | of things. The "Pull request and required checks" problem exists
       | regardless of monorepo or not.
       | 
       | GitHub Actions allows you to only run checks if certain
       | conditions are met, like "only lint markdown if the PR contains
       | *.md files". The moment you decide to use such rules, you have
       | the "Pull request and required checks" problem. No "monorepo"
       | required.
       | 
       | GitHub required checks at this time allow you to use with
       | external services where GitHub has no idea what might run. For
       | this reason, required checks HAVE to pass. There's no "if it
       | runs" step. A required check on an external service might never
       | run, or it might be delayed. Therefore, if GH doesn't have an
       | affirmation that it passed, you can't merge.
       | 
       | It would be wonderful if for jobs that run on GH where GH can
       | know if the action is supposed to run, if required checks could
       | be "require all these checks if they will be triggered".
       | 
       | I have encountered this problem on every non-trivial project I
       | use with GitHub actions; monorepo or not.
        
       | p1necone wrote:
       | There's a workaround for the 'pull request and required check'
       | issue. You create an alternative 'no op' version of each required
       | check workflow that just does nothing and exits with code 0 with
       | the inverse of the trigger for the "real" one.
       | 
       | The required check configuration on github is just based off of
       | job name, so either the trigger condition is true, and the real
       | one has to succeed or the trigger condition is false and the no
       | op one satisfies the PR completion rules instead.
       | 
       | It seems crazy to me that such basic functionality needs such a
       | hacky workaround, but there it is.
        
       | zzo38computer wrote:
       | I do not use GitHub Actions for these purposes, and if I did, I
       | would want to ensure that it is a file that can run locally or
       | whatever else just as well. I don't use GitHub Actions to prevent
       | pull requests from being merged (I will always manage them
       | manually), and do not use GitHub Actions to manage writing the
       | program, for testing the program (it would be possible to do
       | this, but I would insist on doing it in a way that is not vendor-
       | locked to GitHub, and by putting most of the stuff outside of the
       | GitHub Actions file itself), etc.
       | 
       | I do have a GitHub Actions file for a purpose which is not
       | related to the program itself; specifically, for auto-assignment
       | of issues. In this case, it is clearly not intended to run
       | locally (although in this case you could do so anyways if you
       | could install the "gh" program on your computer and run the
       | command mentioned there locally, but it is not necessary since
       | GitHub will do it automatically on their computer).
       | on:         issues:           types:             - opened
       | pull_request:           types:             - opened
       | permissions:         contents: read         issues: write
       | pull-requests: write       jobs:         default:           runs-
       | on: ubuntu-latest           steps:             - run: gh issue
       | edit ${{ github.event.issue.number }} --add-assignee ${{
       | github.repository_owner }}               env:
       | GH_TOKEN: ${{ github.token }}                 GH_REPO: ${{
       | github.repository }}
        
       | ryanisnan wrote:
       | One really interesting omission to this post is how the
       | architecture of GitHub actions encourages (or at the very least
       | makes deceivingly easy) making bad security decisions.
       | 
       | Common examples are secrets. Organization or repository secrets
       | are very convenient, but they are also massive security holes
       | just waiting for unsuspecting victims to fall into.
       | 
       | Repository environments have the ability to have distinct
       | secrets, but you have to ensure that the right workflows can only
       | access the right environments. It's a real pain to manage at
       | scale.
       | 
       | Being able to `inherit` secrets also is a massive footgun, just
       | waiting to leak credentials to a shared action. Search for and
       | leak `AWS_ACCESS_KEY_ID` anyone?
       | 
       | Cross-repository workflow triggering is also a disaster, and in
       | some circumstances you can abuse the differences in configuration
       | to do things the source repository didn't intend.
       | 
       | Other misc. things about GHA also are cool in theory, but fall
       | down in practice. One example is the wait-timer concept of
       | environments. If you have a multi-job workflow using the same
       | environment, wait-timer applies to EACH JOB in the environment.
       | So if you have a build-and-test workflow with 2 jobs, one for
       | build, and one for test, each step will wait `wait-timer` before
       | it executes. This makes things like multi-environment deployment
       | pipelines impossible to use this feature, unless you refactor
       | your workflows.
       | 
       | Overall, I'd recommend against using GHA and looking elsewhere.
        
       ___________________________________________________________________
       (page generated 2025-01-20 23:01 UTC)