HN user

Storment33

76 karma
Posts0
Comments36
View on HN
No posts found.

Fair enough if you've some development environment automation and you want the CI to run it as well so CI is consistent with local development.

Don't know exactly what your doing but others(myself included) are using Mise or Nix on a per project basis to automate the development environment setup and that works well on GitHub Actions.

But I don't think useradd taking 30's on GitHub Actions is a bug or something they need to fix, they've explained why. Unsure about the sudo issues, did not read it carefully.

The problem is some stuff is a real pain to test with static assertions. Such as I was saying about compilers. It would be a real pain to maintain an expected AST in a unit test, then you'd have to go rework it all if you change the shape and or add/remove nodes etc.

You can mix the approaches, have some static assertions(as sanity checks) but make most snapshot tests. Like I said I wouldn't use snapshot testing for a fibonacci method, but there are problems out there that are a real pain to test via static assertions.

I mean...

They told you why it takes so long no? the runners come by default with loads of programming languages installed like Rust, Haskell, Node, Python, .Net etc so it sets all that up per user add.

I would also question why your adding users on an ephemeral runner.

This is what I done, GitHub Actions is basically a command line as a service for my projects. It does nothing but checkout the code, means I can do all the releasing, artefact uploading, compiling & testing etc locally.

I mean all CIs work out of the box, although I have no interest in self hosting CI.

Jenkins is probably a bit like Java, technically it is fine. The problem is really where/who typically uses it and as there is so much freedom it is really easy to make a monster. Where as for Go it is a lot harder to write terrible unmaintainable code compared to Java.

It is called snapshot testing, very valid technique. Maybe not best suited to a mathematical function like they have here, but I have found it useful for stuff like compilers asserting on the AST, where it would be a pain to write out and assert on the output and may also change shape.

Yes I am seeing what your saying, it can start of simple and people will choose the path of least resistance and you'll end up with a ball of mud eventually. Fortunately I have not come across anything that bad yet.

I know it is a made up example, but I am not sure Python would improve the situation. I would be looking at either Docker or SBOMs to try and improve the situation and then hopefully the release process would become a lot simpler.

Jobs run in parallel, so if you used Make you could have one job called 'formatting' calling 'make check-formatting', one called linting calling ''make check-linting', one called 'compiling' calling 'make compile' etc.

I use to have my Makefile call out and do `docker build ...` and `docker run ...` etc with a volume mount of the source code to manage and maintain tooling versions etc.

It works okay, better than a lot of other workflows I have seen. But it is a bit slow, a bit cumbersome(for langs like Go or Node.js that want to write to HOME) and I had some issues on my ARM Macbook about no ARM images etc.

I would recommend taking a look at Nix, it is what I switched to.

* It is faster. * Has access to more tools. * Works on ARM, X86 etc.

However it’s really easy to go from a simple shell script running a few commands to something significantly more complex just to do something seemingly simple, like parse a semantic version, make an api call and check the status code etc, etc.

Maybe I keep making the wrong assumption that everyone is using the same tools the same way and thats why my opinions seem very strong. But I wouldn't even think of trying to "parse a semantic version" in shell, I am treating the shell scripts and task runners as plumbing, I would be handing that of a dedicated tool to action.

I don't touch Windows so I would not know.

The same Python testing code runs on all three platforms.

I have no objections to Python being used for testing, I use it myself for the end to end tests in my projects. I just don't think Python as a build script/task runner is a good idea, see below where I got Claude to convert one of my open source projects for an example.

UV scripts are great for this type of workflow

So previously when I have seen Python used as a task runner I think they used UV to call it. Although I don't think they had as a complete solution as your here auto-installing UV etc.

Although the example you've linked is installing UV if missing, the version is not pinned, I also don't think it is handling missing Python which is not pinned even if installed locally. So you could get different versions on CI vs locally.

While yes you are removing some of the dependencies problems created via using Python over Make/Shell I don't think this completely solves it.

Something like this can start out simple and can scale much more than the limitations of bash which can be abundant at times

I personally haven't witnessed anytime I would consider the scales to have tipped in favour of Python and I would be concerned if they ever do, as really the task runner etc should be plumbing, so it should be simple.

That being said, I still make some shell scripts because executing other applications is first class support in bash but not so much in python but after discovering this I might create some new scripts with python with automated uv because I end up installing uv on many devices anyway (because uv's really good for python)

Using Python/UV to do anything more complex than my example PR above?

I was doing something similar when moving from Earthly. But I have since moved to Nix to manage the environment. It is a lot better of a developer experience and faster! I would checkout an environment manager like Nix/Mise etc so you can have the same tools etc locally and on CI.

Yeah, tends to happen a lot when you hold strong opinions with strong conviction :) Not that it's wrong or anything, but it's highly subjective in the end.

Strong opinions, loosely held :)

Typically I see larger issues being created from "under-engineering" and just rushing with the first idea people can think of when they implement things, rather than "over-engineering"

Funnily enough running with the first idea I think is creating a lot of the "over-engineering" I am seeing. Not stopping to consider other simpler solutions or even if the problem needs/is worth solving in the first place.

Yeah, tends to happen a lot when you hold strong opinions with strong conviction :) Not that it's wrong or anything, but it's highly subjective in the end.

I quickly asked Claude to convert one of my open source repos using Make/Nix/Shell -> Python/Nix to see how it would look. It is actually one of the better Python as a task runners I have seen.

* https://github.com/DeveloperC286/clean_git_history/pull/431

While the Python version is not as bad as I have seen previously, I am still struggling to see why you'd want it over Make/Shell.

It introduces more dependencies(Python which I solved via Nix) but others haven't solved this problem and the Python script has dependencies(such as Click for the CLI).

It is less maintainable as it is more code, roughly x3 the amount of the Makefile.

To me the Python code is more verbose and not as simple compared to the Makefile's target so it is less readable as well.

Huh? Who cares if the script is .sh, .bash, Makefile, Justfile, .py, .js or even .php?

Me, typically I have found it to be a sign of over-engineering and found no benefits over just using shell script/task runner, as all it should be is plumbing that should be simple enough that a task runner can handle it.

If it works it works, as long as you can run it locally, it'll be good enough,

Maybe when it is your own personal project "If it works it works" is fine. But when you come to corporate environment there starts to be issues of readability, maintainability, proprietary tooling, additional dependencies etc I have found when people start to over-engineer and use programming languages(like Python).

E.g.

never_inline 30 minutes ago | parent | prev | next [–]

Build a CLI in python or whatever which does the same thing as CI, every CI stage should just call its subcommands.

However,

and sometimes it's an even better idea to keep it in the same language the rest of the project is

I'll agree. Depending on the project's language etc other options might make sense. But personally so far everytime I have come across something not using a task runner it has just been the wrong decision.

If your CI can do things that you can't do locally: that is a problem.

Completely agree.

I'm a huge fan of "train as you fight", whatever build tools you have locally should be what's used in CI.

That is what I am doing, having my GitHub Actions just call the Make targets I am using locally.

I mean, at some point you are bash calling some other language anyway.

Yes, shell scripts and or task runners(Make, Just, Task etc) are really just plumbing around calling other tools. Which is why it feels like a smell to me when you need something more.

I agree with #2, I meant more if you are calling out to something that is not a task runner(Make, Taskfile, Just etc) or a shell script thats a bit of a smell to me. E.g. I have seen people call out to Python scripts etc and it concerns me.

  > For the love of all that is holy, don’t let GitHub Actions
  > manage your logic. Keep your scripts under your own damn
  > control and just make the Actions call them!
I mean your problem was not `build.rs` here and Makefiles did not solve it, was your logic not already in `build.rs` which was called by Cargo via GitHub Actions?

The problem was the environment setup? You couldn't get CUE on Linux ARM and I am assuming when you moved to Makefiles you removed the need for CUE or something? So really the solution was something like Nix or Mise to install the tooling, so you have the same tooling/version locally & on CI?

I would disagree with 1. if you need anything more than shell that starts to become a smell to me. The build/testing process etc should be simple enough to not need anything more.

I agree there is stuff you can't test locally, but in my experience people most of the time are complaining about stuff they should have local feedback loops for such as compiling, testing, end to end testing etc.

You give some good examples and I agree they is CI specific stuff that can only be really tested on CI, but it a subset of what I generally see people complaining about.

can't locally do things like automatically creating a release in a Github workflow, sending test results as a comment to PRs automatically and uploading CI pipeline artifacts locally.

uploading CI pipeline artifacts locally

I actually testing this locally before opening up a pull request to add it. I just have my workflow call out to a make target, so I can do the same locally if I have the right credentials using the same make target.

E.g. this workflow trigger on a release.

```yaml name: Continuous Delivery (CD)

on: release: types: [published]

# https://docs.github.com/en/actions/using-jobs/assigning-perm... permissions: contents: write packages: write

jobs: publish-binary: name: Publish Binary runs-on: ${{ matrix.architecture }} strategy: matrix: architecture: [ubuntu-24.04, ubuntu-24.04-arm] steps: - name: Checkout code. uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Nix. uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0 - name: Publish binary. run: nix develop -c make publish-binary RELEASE="${GITHUB_REF_NAME}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by GitHub Actions. ```

Which after building the binary calls this script

```bash #!/usr/bin/env sh

set -o errexit set -o xtrace

if [ "$#" -ne 2 ]; then echo "Usage: $0 RELEASE_TAG TARGET" echo "$#" exit 1 fi

RELEASE="$1" TARGET="$2"

tar -czvf "${TARGET}.tar.gz" -C "target/${TARGET}/release" "clean_git_history" gh release upload "${RELEASE}" "${TARGET}.tar.gz" rm "${TARGET}.tar.gz" ```

So I was able to test large parts of this locally first via `make publish-binary RELEASE="test-release"`.

I agree, yet unfortunately most of the time I personally see people complaining it is about builds or tests unable to reproduce failures etc locally or unable to run end to end tests and have to push to CI to get them ran.