[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)