Skip to content

Latest commit

 

History

History
369 lines (244 loc) · 12.4 KB

api.md

File metadata and controls

369 lines (244 loc) · 12.4 KB

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}`,
  // ...
});