Yeetfile API#
Yeet uses goja 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.
To 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.
$#
$ lets you construct shell commands using tagged templates. This lets you build whatever shell commands you want by mixing Go and JavaScript values freely.
Example:
$`CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -s -w -extldflags "-static" -X "within.website/x.Version=${git.tag()}"`;
deb#
Helpers for building Debian packages.
deb.build#
Builds 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.
The resulting Debian package path will be returned as a string.
Usage:
deb.build(package);
["amd64", "arm64"].forEach((goarch) =>
deb.build({
name: "yeet",
description: "Yeet out actions with maximum haste!",
homepage: "https://techaro.lol",
license: "MIT",
goarch,
build: ({ bin }) => {
go.build("-o", `${bin}/yeet`, "./cmd/yeet");
},
}),
);
docker#
Aliases for docker commands.
docker.build#
An alias for the docker build command. Builds a docker image in the current working directory's Dockerfile.
Usage:
docker.build(tag);
docker.build("ghcr.io/xe/site/bin");
docker.push("ghcr.io/xe/site/bin");
docker.push#
Pushes a docker image to a registry. Analogous to docker push in the CLI.
Usage:
docker.push(tag);
docker.build("ghcr.io/xe/site/bin");
docker.push("ghcr.io/xe/site/bin");
file#
file.install#
Copies 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.
Usage:
file.install(src, dest);
file.install("LICENSE", `${doc}/LICENSE`);
git#
Helpers for the Git version control system.
git.repoRoot#
Returns the repository root as a string.
git.repoRoot();
const repoRoot = git.repoRoot();
file.copy(`${repoRoot}/LICENSE`, `${doc}/LICENSE`);
git.tag#
Returns 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.
Usage:
git.tag();
const version = git.tag();
gitea#
Helpers for integrating with Gitea servers.
gitea.uploadPackage#
Uploads 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.
Usage:
gitea.uploadPackage(owner, distro, component, fname)
gitea.uploadPackage(
"Techaro",
"yeet",
"unstable",
"./var/yeet-0.0.8.x86_64.rpm",
);
go#
Helpers for the Go programming language.
go.build#
Runs 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.
Usage:
go.build(args);
go.build("-o", `${out}/usr/bin/`);
go.install#
Runs go install. Not useful for cross-compilation.
Usage:
go.install();
go.install();
log#
Logging functions.
log.println#
Prints log data to standard output.
Usage:
log.println(...);
log.println(`built package ${pkgPath}`);
rpm#
Helpers for building RPM packages and docker images out of a constellation of RPM packages.
rpm.build#
Builds 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.
The resulting RPM path will be returned as a string.
Usage:
rpm.build(package);
["amd64", "arm64"].forEach((goarch) =>
rpm.build({
name: "yeet",
description: "Yeet out actions with maximum haste!",
homepage: "https://techaro.lol",
license: "MIT",
goarch,
build: ({ bin }) => {
go.build("-o", `${bin}/yeet`, "./cmd/yeet");
},
}),
);
yeet#
This contains various "other" functions that don't have a good place to put them.
yeet.cwd#
The current working directory. This is a constant value and is not updated at runtime.
Usage:
log.println(yeet.cwd);
yeet.dateTag#
A 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).
Usage:
docker.build(`ghcr.io/xe/site/bin:${git.tag()}-${yeet.dateTag}`);
yeet.getenv#
Gets an environment variable and returns it as a string, optionally returning an empty string if the variable is not found.
Usage:
yeet.getenv(name);
const someValue = yeet.getenv("SOME_VALUE");
yeet.run / yeet.runcmd#
Runs an arbitrary command and returns any output as a string.
Usage:
yeet.run(cmd, arg1, arg2, ...);
yeet.run(
"protoc",
"--proto-path=.",
`--proto-path=${git.repoRoot()}/proto`,
"foo.proto",
);
yeet.setenv#
Sets an environment variable for the process yeet is running in and all children.
Usage:
yeet.setenv(key, val);
yeet.setenv("GOOS", "linux");
yeet.goos / yeet.goarch#
The GOOS/GOARCH value that yeet was built for. This typically corresponds with the OS and CPU architecture that yeet is running on.
Building native packages#
When 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:
["amd64", "arm64"].forEach((goarch) =>
[deb, rpm, tarball].forEach((method) =>
method.build({
name: "yeet",
description: "Yeet out scripts with maximum haste!",
homepage: "https://techaro.lol",
license: "MIT",
goarch,
build: ({ bin }) => {
go.build("-o", `${bin}/yeet`, "./cmd/yeet");
},
}),
),
);
Build settings#
The following settings are supported:
| Name | Example | Description |
|---|---|---|
name |
xeiaso.net-yeet |
The name of the package. This should be unique across the system. |
version |
1.0.0 |
The version of the package, if not set then it will be inferred from the git version. |
description |
Yeet out scripts with haste! |
The human-readable description of the package. |
homepage |
https://xeiaso.net |
The URL for the homepage of the package. |
group |
Network |
If set, the RPM group that this package belongs to. |
license |
MIT |
The license that the contents of this package is under. |
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. |
replaces |
["foo", "bar"] |
Any packages that this package conflicts with or replaces. |
depends |
["foo", "bar"] |
Any packages that this package depends on (such as C libraries for CGo code). |
emptyDirs |
["/var/lib/yeet"] |
Any empty directories that should be created when the package is installed. |
configFiles |
{"./.env.example": "/var/lib/yeet/.env"} |
Any configuration files that should be copied over on install, but managed by administrators after installation. |
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. |
files |
{} |
Any other static files that should be copied in-place to a path in the target filesystem. |
Packages MUST define a build function and tarball packages MAY define a mkFilename function.
build function#
Every 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.
The signature of build roughly follows this TypeScript type:
interface BuildInput {
// output folder, usually the package root
out: string;
// binary folder, ${out}/bin for tarballs or ${out}/usr/bin for OS packages
bin: string;
// documentation folder, ${out}/doc for tarballs or ${out}/usr/share/${pkg.name}/doc for OS packages
doc: string;
// configuration folder, ${out}/run for tarballs or ${out}/etc/${pkg.name} for OS packages
etc: string;
// systemd unit folder, ${out}/run for tarballs or ${out}/usr/lib/systemd/system for OS packages
systemd: string;
}
function build({...}: BuildInput) => {
// ...
};
mkFilename function#
When building a tarball, you MAY define a mkFilename function to customize the generated filename. If no mkFilename function is specified, the filename defaults to:
const mkFilename = ({name, version, platform, goarch}) =
`${name}-${version}-${platform}-${goarch}`;
For example, to reduce the filename to the name and the version:
tarball.build({
// ...
mkFilename: ({ name, version }) => `${name}-${version}`,
// ...
});