6 ms·
I do that in my Go projects. In fact my "scripts" are actually part of the main executable. I use cmd-line args to invoke the needed functionality. For exampl
by kjksf 3y ago
I do that in my Go projects.
In fact my "scripts" are actually part of the main executable. I use cmd-line args to invoke the needed functionality.
For example, in the past I would have written a Python script to deploy my Go binary to a server, possibly using tools like Fabric that provide functionality to make it easier.
Today I add `-deploy-hetzner` cmd-line to my Go binary and it does the work. It builds itself, copies the binary to the server, kills the old instances, configures caddy if needed, starts newly uploaded instance etc.
For example my deploy.go is 409 lines of code, which is not that bad. You can see exactly how this works: https://github.com/kjk/edna/blob/main/server/deploy.go https://github.com/kjk/edna/blob/main/server/deploy.go
I standardized on how I deploy things so deploy.go is mostly re-used among several projects.
Writing this code isn't much more difficult that what I used to write in Python.
This kind of code can be shorter because I don't have to handle errors, I just panic if something goes wrong.
I like that I don't have to switch between different languages and that I have full control and understanding over what happens. Fabric used to be a bit of a black box.
I even wrote an article about this idea: https://blog.kowalczyk.info/article/4b1f9201181340099b698246857ea98d/using-go-instead-of-bash-for-scripts.html https://blog.kowalczyk.info/article/4b1f9201181340099b698246...
- zer00eyz 3y agoIm a big fan of //go:build exclude ... and having separate CLI scripts in a project where I can. Candidly I think that it's much easier to do this in go (or rust), rather than say python/ruby/node as I can use complied binaries without needing a run time. Edit: //go:build ignore is idiomatic
- bbkane 3y agoDo build-excluded files get tested with `go test`? (tbf, not sure it's practical to test most scripty tasks)
- zer00eyz 3y agoThink of this as a way to have a file with package main, and a func main that does not interfere with your normal build process... The best example of this, and a decent util is this: https://go.dev/src/crypto/tls/generate_cert.go https://go.dev/src/crypto/tls/generate_cert.go All of the real testing happens elsewhere this just provides utility.
- vundercind 3y agoGo’s excellent for writing development tools and “scripts” if you have to support development on heterogenous platforms. No per-platform install instructions, no “ok but you have to run this in WSL2… you don’t have that? Oh god, ok, let’s find those instructions…”, no “oh fuck the flags for that are different on BSD and Linux, so this breaks on macOS”. “Wait the command’s python3 not python, on your system? And also it’s erroring even after you fix that? Shit you’re still on 3.8, we use features that weren’t included until 3.10…” “Unzip this single binary and run it. Tell your OS to trust it if it hassles you. That’s it.” C# with mono might be close to as good? Not sure. Rust’s probably OK but a bit of an investment when you’re just trying to dash off some quick tool or script. C++ and C can do it but you definitely don’t want to. Java’s obviously out (ok, now update your JRE… wait, your env vars are all fucked up, hold on…). Go’s also highly likely to be something another developer with or without Go experience can read and tweak after the person who wrote it leaves, without much trouble.
- sethammons 3y agoWhy use build tags for this over ./cmd/$toolname/main.go?
- llmblockchain 3y agoI do this as well, but I pass two main arguments to my main executable task, and args. For example: go run cmd/server/main.go --task db --args migrate go run cmd/server/main.go --task cron --args reset-trial-accounts etc.
- GeneralMayhem 3y agoI use https://github.com/spf13/cobra https://github.com/spf13/cobra religiously for this kind of thing - it handles all the annoying corner cases of parsing flags, and also has an intuitive notion of subcommands (with basic usage/help text generated) for picking which task you want to run with positional arguments.
- llmblockchain 3y agoI'll have to mess with it and see. It looks like it could make the general CLI ux better :)
- emseetech 3y agoGo feels especially suited for moving between application code and command line tools.
- jlubawy 3y agoI tend to use go for "scripts" in non-go repos (typescript, C, etc) just for the simplicity of "you only need to install go" and pretty much all functionality is included in the standard library (usually something like JSON/XML/CSV parsing). I'm OK with python for scripts, but go "just works".
- fire_lake 3y agoPython can be annoying for scripts because they are often hard to run on another machine due to the dependency story. I think Go scripts have a much better odd of “just working”with only the Go toolchain installed.
- rglullis 3y agoThis seems like a terrible case of not separating concerns and needless optimization. It may work for you, but what if someone who does not know Go but wants to use your project on a provider that is not hetzner?
- dotancohen 3y agoNot OP, but I presume that one could add `-deploy-aws` cmd-line to the Go binary with whatever steps AWS requires.
- rglullis 3y agoYeah, this is the way to end up with ad-hoc, bug-ridden, half-baked implementation of fabric (or ansible, salt, helm, nix, or any tool that is more appropriate for this job) And you haven't addressed the issue that whoever is performing the role of DevOps on this project must know Go.
- dotancohen 3y agoDo fabric,ansible, salt, helm, or nix have the functionality of deploying to cloud infrastructures? There is a lot more to deploying to cloud infrastructures then just provisioning a server. I've never seen these tools used in this capacity, especially nix.
- pxc 3y agoI think such things have existed, but Nix deployment tools being relatively small projects with small teams or solo devs, a more common approach is to piggyback off of other IaC tools provisioning cloud infrastructure, e.g. by templating Terraform in Nix¹. From a Nix user's perspective, this leaves a lot to be desired, because tools like Terraform are much less reliable than Nix tools that target local machines, and their management of, say, a VPC, is much less comprehensive than NixOS' management of an individual operating system. And they're slow as hell. But for the most part these issues are inherited from the APIs cloud providers expose, which don't meaningfully or uniformly support immutability. -- 1: https://github.com/terranix/terranix https://github.com/terranix/terranix