Yeet those builds out!
at main 369 lines 13 kB view raw view rendered
1# Yeetfile API 2 3Yeet uses [goja](https://pkg.go.dev/github.com/dop251/goja#section-readme) to execute JavaScript. As such, it does not have access to NPM or other external JavaScript libraries. You also cannot import code/data from other files. These are not planned for inclusion into yeet. If functionality is required, it should be added to yeet itself. 4 5To make it useful, yeet exposes a bunch of helper objects full of tools. These tools fall in a few categories, each has its own section. 6 7## `$` 8 9`$` lets you construct shell commands using [tagged templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). This lets you build whatever shell commands you want by mixing Go and JavaScript values freely. 10 11Example: 12 13```js 14$`CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -s -w -extldflags "-static" -X "within.website/x.Version=${git.tag()}"`; 15``` 16 17## `deb` 18 19Helpers for building Debian packages. 20 21### `deb.build` 22 23Builds a Debian package with a descriptor object. See the native packages section for more information. The important part of this is your `build` function. The `build` function is what will turn your package source code into an executable in `out` somehow. 24 25The resulting Debian package path will be returned as a string. 26 27Usage: 28 29`deb.build(package);` 30 31```js 32["amd64", "arm64"].forEach((goarch) => 33 deb.build({ 34 name: "yeet", 35 description: "Yeet out actions with maximum haste!", 36 homepage: "https://techaro.lol", 37 license: "MIT", 38 goarch, 39 40 build: ({ bin }) => { 41 go.build("-o", `${bin}/yeet`, "./cmd/yeet"); 42 }, 43 }), 44); 45``` 46 47## `docker` 48 49Aliases for `docker` commands. 50 51### `docker.build` 52 53An alias for the `docker build` command. Builds a docker image in the current working directory's Dockerfile. 54 55Usage: 56 57`docker.build(tag);` 58 59```js 60docker.build("ghcr.io/xe/site/bin"); 61docker.push("ghcr.io/xe/site/bin"); 62``` 63 64### `docker.push` 65 66Pushes a docker image to a registry. Analogous to `docker push` in the CLI. 67 68Usage: 69 70`docker.push(tag);` 71 72```js 73docker.build("ghcr.io/xe/site/bin"); 74docker.push("ghcr.io/xe/site/bin"); 75``` 76 77## `file` 78 79### `file.install` 80 81Copies from a file from one place to another whilst preserving the file mode, analogous to `install -d` on Linux. Automatically creates directories in the `dest` path if they don't exist already. 82 83Usage: 84 85`file.install(src, dest);` 86 87```js 88file.install("LICENSE", `${doc}/LICENSE`); 89``` 90 91## `git` 92 93Helpers for the Git version control system. 94 95### `git.repoRoot` 96 97Returns the repository root as a string. 98 99`git.repoRoot();` 100 101```js 102const repoRoot = git.repoRoot(); 103 104file.copy(`${repoRoot}/LICENSE`, `${doc}/LICENSE`); 105``` 106 107### `git.tag` 108 109Returns the output of `git describe --tags`. Useful for getting the "current version" of the repo, where the current version will likely be different forward in time than it is backwards in time. 110 111Usage: 112 113`git.tag();` 114 115```js 116const version = git.tag(); 117``` 118 119## `gitea` 120 121Helpers for integrating with Gitea servers. 122 123### `gitea.uploadPackage` 124 125Uploads a binary package to Gitea, silently failing if the package is not a `.deb` or `.rpm` file. Gitea configuration is done with flags or the configuration file. 126 127Usage: 128 129`gitea.uploadPackage(owner, distro, component, fname)` 130 131```js 132gitea.uploadPackage( 133 "Techaro", 134 "yeet", 135 "unstable", 136 "./var/yeet-0.0.8.x86_64.rpm", 137); 138``` 139 140## `go` 141 142Helpers for the Go programming language. 143 144### `go.build` 145 146Runs `go build` in the current working directory with any extra arguments passed in. This is useful for building and installing Go programs in an RPM build context. 147 148Usage: 149 150`go.build(args);` 151 152```js 153go.build("-o", `${out}/usr/bin/`); 154``` 155 156### `go.install` 157 158Runs `go install`. Not useful for cross-compilation. 159 160Usage: 161 162`go.install();` 163 164```js 165go.install(); 166``` 167 168## `log` 169 170Logging functions. 171 172### `log.println` 173 174Prints log data to standard output. 175 176Usage: 177 178`log.println(...);` 179 180```js 181log.println(`built package ${pkgPath}`); 182``` 183 184## `rpm` 185 186Helpers for building RPM packages and docker images out of a constellation of RPM packages. 187 188### `rpm.build` 189 190Builds an RPM package with a descriptor object. See the RPM packages section for more information. The important part of this is your `build` function. The `build` function is what will turn your package source code into an executable in `out` somehow. Everything in `out` corresponds 1:1 with paths in the resulting RPM. 191 192The resulting RPM path will be returned as a string. 193 194Usage: 195 196`rpm.build(package);` 197 198```js 199["amd64", "arm64"].forEach((goarch) => 200 rpm.build({ 201 name: "yeet", 202 description: "Yeet out actions with maximum haste!", 203 homepage: "https://techaro.lol", 204 license: "MIT", 205 goarch, 206 207 build: ({ bin }) => { 208 go.build("-o", `${bin}/yeet`, "./cmd/yeet"); 209 }, 210 }), 211); 212``` 213 214## `yeet` 215 216This contains various "other" functions that don't have a good place to put them. 217 218### `yeet.cwd` 219 220The current working directory. This is a constant value and is not updated at runtime. 221 222Usage: 223 224```js 225log.println(yeet.cwd); 226``` 227 228### `yeet.dateTag` 229 230A constant string representing the time that yeet was started in UTC. It is formatted in terms of `YYYYmmDDhhMM`. This is not updated at runtime. You can use it for a "unique" value per invocation of yeet (assuming you aren't a time traveler). 231 232Usage: 233 234```js 235docker.build(`ghcr.io/xe/site/bin:${git.tag()}-${yeet.dateTag}`); 236``` 237 238### `yeet.getenv` 239 240Gets an environment variable and returns it as a string, optionally returning an empty string if the variable is not found. 241 242Usage: 243 244`yeet.getenv(name);` 245 246```js 247const someValue = yeet.getenv("SOME_VALUE"); 248``` 249 250### `yeet.run` / `yeet.runcmd` 251 252Runs an arbitrary command and returns any output as a string. 253 254Usage: 255 256`yeet.run(cmd, arg1, arg2, ...);` 257 258```js 259yeet.run( 260 "protoc", 261 "--proto-path=.", 262 `--proto-path=${git.repoRoot()}/proto`, 263 "foo.proto", 264); 265``` 266 267### `yeet.setenv` 268 269Sets an environment variable for the process yeet is running in and all children. 270 271Usage: 272 273`yeet.setenv(key, val);` 274 275```js 276yeet.setenv("GOOS", "linux"); 277``` 278 279### `yeet.goos` / `yeet.goarch` 280 281The GOOS/GOARCH value that yeet was built for. This typically corresponds with the OS and CPU architecture that yeet is running on. 282 283## Building native packages 284 285When using the `deb.build`, `rpm.build`, or `tarball.build` functions, you can create native packages from arbitrary yeet expressions. This allows you to cross-compile native packages from a macOS or other Linux system. As an example, here is how the yeet packages are built: 286 287```js 288["amd64", "arm64"].forEach((goarch) => 289 [deb, rpm, tarball].forEach((method) => 290 method.build({ 291 name: "yeet", 292 description: "Yeet out scripts with maximum haste!", 293 homepage: "https://techaro.lol", 294 license: "MIT", 295 goarch, 296 297 build: ({ bin }) => { 298 go.build("-o", `${bin}/yeet`, "./cmd/yeet"); 299 }, 300 }), 301 ), 302); 303``` 304 305### Build settings 306 307The following settings are supported: 308 309| Name | Example | Description | 310| :-------------- | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 311| `name` | `xeiaso.net-yeet` | The name of the package. This should be unique across the system. | 312| `version` | `1.0.0` | The version of the package, if not set then it will be inferred from the git version. | 313| `description` | `Yeet out scripts with haste!` | The human-readable description of the package. | 314| `homepage` | `https://xeiaso.net` | The URL for the homepage of the package. | 315| `group` | `Network` | If set, the RPM group that this package belongs to. | 316| `license` | `MIT` | The license that the contents of this package is under. | 317| `goarch` | `amd64` / `arm64` | The GOARCH value corresponding to the architecture that the RPM is being built for. If you want to build a `noarch` package, put `any` here. | 318| `replaces` | `["foo", "bar"]` | Any packages that this package conflicts with or replaces. | 319| `depends` | `["foo", "bar"]` | Any packages that this package depends on (such as C libraries for CGo code). | 320| `emptyDirs` | `["/var/lib/yeet"]` | Any empty directories that should be created when the package is installed. | 321| `configFiles` | `{"./.env.example": "/var/lib/yeet/.env"}` | Any configuration files that should be copied over on install, but managed by administrators after installation. | 322| `documentation` | `{"./README.md": "README.md"}` | Any documentation files that should be copied to the `doc` folder of a tarball or be put in `/usr/share/doc` in an OS package. Try to include enough documentation that users can troubleshoot the program completely offline. | 323| `files` | `{}` | Any other static files that should be copied in-place to a path in the target filesystem. | 324 325Packages MUST define a `build` function and tarball packages MAY define a `mkFilename` function. 326 327### `build` function 328 329Every package definition MUST contain a `build` function that describes how to build the software. The build function takes one argument and returns nothing. If the build fails, throw an Exception with `throw`. 330 331The signature of `build` roughly follows this TypeScript type: 332 333```ts 334interface BuildInput { 335 // output folder, usually the package root 336 out: string; 337 // binary folder, ${out}/bin for tarballs or ${out}/usr/bin for OS packages 338 bin: string; 339 // documentation folder, ${out}/doc for tarballs or ${out}/usr/share/${pkg.name}/doc for OS packages 340 doc: string; 341 // configuration folder, ${out}/run for tarballs or ${out}/etc/${pkg.name} for OS packages 342 etc: string; 343 // systemd unit folder, ${out}/run for tarballs or ${out}/usr/lib/systemd/system for OS packages 344 systemd: string; 345} 346 347function build({...}: BuildInput) => { 348 // ... 349}; 350``` 351 352### `mkFilename` function 353 354When building a tarball, you MAY define a `mkFilename` function to customize the generated filename. If no `mkFilename` function is specified, the filename defaults to: 355 356```js 357const mkFilename = ({name, version, platform, goarch}) = 358 `${name}-${version}-${platform}-${goarch}`; 359``` 360 361For example, to reduce the filename to the name and the version: 362 363```js 364tarball.build({ 365 // ... 366 mkFilename: ({ name, version }) => `${name}-${version}`, 367 // ... 368}); 369```