Wand
A simple and powerful toolkit for Mage.
Install / Use
/learn @svengreb/WandREADME
Features
wand is a toolkit for common and often recurring project processes for the task automation tool [Mage][1]. The provided [API packages][74] allow users to compose their own, reusable set of tasks and helpers or built up on the [reference implementation][56].
- Adapts to any “normal“ or [“mono“][105] repository layout — handle as many module commands as you want. wand uses an abstraction by managing every
mainpackage as application so that tasks can be processed for all or just individual commands. - Runs any
mainpackage of a [Go module][39] without the requirement for the user to install it beforehand — Run any command of a Go module using the [module-aware][119]pkg@versionsyntax, or optionally cache executables in a local directory within the project root, using the [gotoolrunner][93]. See the “Command Runners“ sections below for details. - Comes with support for basic [Go toolchain][48] commands and popular modules from the Go ecosystem — run common commands like
go build,go installandgo testor great tools like [gofumpt][62], [golangci-lint][60] and [gox][61] in no time.
See the API and “Elder Wand“ sections for more details. The user guides for more information about how to build your own tasks and runners and the examples for different repositories layouts (single or [“monorepo“][105]) and use cases.
Motivation
<!--lint disable no-heading-punctuation-->Why Mage?
Every project involves processes that are often recurring. These can mostly be done with the tools supplied with the respective programming language, which in turn, in many cases, involve more time and the memorizing of longer commands with their flags and parameters. In order to significantly reduce this effort or to avoid it completely, project task automation tools are used which often establish a defined standard to enable the widest possible use and unify tasks. They offer a user-friendly and comfortable interface to handle the processes consistently with time savings and without the need for developers to remember many and/or complex commands. But these tools come with a cost: the introduction of standards and the restriction to predefined ways how to handle tasks is also usually the biggest disadvantage when it comes to adaptability for use cases that are individual for a single project, tasks that deviate from the standard or not covered by it at all.
[Mage][1] is a project task automation tool which gives the user complete freedom by not specifying how tasks are solved, but only how they are started and connected with each other. This is an absolute advantage over tools that force how how a task has to be solved while leaving out individual and project specific preferences.
If you would now ask me “But why not just use [Make][9]?“, my answer would be “Why use a tool that is not native to the programming language it is intended for?“.
Make has somehow become a popular choice as task automation tool for Go projects and up to today I don‘t get it. Don‘t get me wrong: this is no bad talking against Make but a clarification that it is not intended for Go but rather for C projects, e.g. [the Linux kernel][3], since [Make is also written in C][38]. Even [Go itself is built using shell and Windows DOS scripts][36] instead of Make.
If you take a closer look, Make is nothing more than a [DSL][106] for [shell commands][37] so using shell/Windows DOS scripts directly instead is a way more flexible option. Therefore Make can not fullfil an important criteria: full cross-platform compatibility. The command(s) that each task runs must be available on the system, e.g. other tools must be installed globally and available in the [executable search path][109], as well as requiring the syntax to be compatible with the underlying shell which makes it hard to use [shell builtin][110] commands like cd.
In my opinion, a task automation tool for a project should always be written in the same programming language that it is intended for. This concept has already been proven for many other languages, e.g. official tools like [cargo][104] for Rust and [NPM][6] for Node.js‘s or community projects like [Gradle][7] or [Maven][8] for Java. All of them can natively understand and interact with their target programming language to provide the widest range of features, good stability and often also ways to simply extend their functionality through plugin systems.
This is where Mage comes in:
- Written in [pure Go without any external dependencies][22] for fully native compatibility and easy expansion.
- [No installation][102] required.
- Allows to [declare dependencies between targets][97] in a makefile-style tree and optionally [runs them in parallel][98].
- Targets can be defined in shared packages and [imported][100] in any [Magefile][99]. No mechanics like plugins or extensions required, just use any Go module and the whole Go ecosystem.
Why wand?
While Mage is often already sufficient on its own, I‘ve noticed that I had to implement almost identical tasks over and over again when starting a new project or migrating an existing one to Mage. Even though the actual [target functions][101] could be moved into their own Go module to allow to simply [import them][100] in different projects, it was often required to copy & paste code across projects that can not be exported that easily. That was the moment where I decided to create a way that simplifies the integration and usage of Mage without loosing any of its flexibility and dynamic structure.
Please note that this package has mainly been created for my personal use in mind to avoid copying source code between my projects. The default configurations or reference implementation might not fit your needs, but the API packages have been designed so that they can be flexibly adapted to different use cases and environments or used to create and compose your own [wand.Wand][72].
See the API and “Elder Wand“ sections to learn how to adapt or extend wand for your project.
<!--lint enable no-heading-punctuation-->Wording
Since wand is a toolkit for [Mage][1], is partly makes use of an abstract naming scheme that matches the fantasy of magic which in case of wand has been derived from the fantasy novel [“Harry Potte
