{"id":29675787,"url":"https://github.com/oxidecomputer/buildomat","last_synced_at":"2025-07-22T23:38:45.534Z","repository":{"id":37178406,"uuid":"414061686","full_name":"oxidecomputer/buildomat","owner":"oxidecomputer","description":"a software build labour-saving device","archived":false,"fork":false,"pushed_at":"2025-06-06T19:51:31.000Z","size":1627,"stargazers_count":59,"open_issues_count":40,"forks_count":3,"subscribers_count":23,"default_branch":"main","last_synced_at":"2025-06-06T20:55:48.474Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oxidecomputer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-10-06T03:58:04.000Z","updated_at":"2025-05-12T22:38:21.000Z","dependencies_parsed_at":"2023-11-21T04:27:07.965Z","dependency_job_id":"7a2f494c-932d-4e30-adf9-d90776023228","html_url":"https://github.com/oxidecomputer/buildomat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/oxidecomputer/buildomat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fbuildomat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fbuildomat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fbuildomat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fbuildomat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxidecomputer","download_url":"https://codeload.github.com/oxidecomputer/buildomat/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fbuildomat/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266591233,"owners_count":23953082,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-22T23:38:39.150Z","updated_at":"2025-07-22T23:38:45.513Z","avatar_url":"https://github.com/oxidecomputer.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"./www/buildomat_wide.png\" alt=\"hammer logo\"\u003e\u003cbr\u003e\n\u003cb\u003eB U I L D O M A T\u003c/b\u003e\u003cbr\u003e\na software build labour-saving device\u003cbr\u003e\n\u003c/p\u003e\n\n\u003chr\u003e\n\nBuildomat manages the provisioning of ephemeral UNIX systems (e.g., instances\nin AWS EC2) on which to run software builds.  It logs job output, collects\nbuild artefacts, and reports status.  The system integrates with GitHub through\nthe Checks API, to allow build jobs to be triggered by pushes and pull\nrequests.\n\n## Components\n\nBuildomat is made up of a variety of crates, loosely grouped into areas\nof related functionality:\n\n```\n$ cargo xtask crates\nbuildomat                    /bin\nbuildomat-agent              /agent\nbuildomat-bunyan             /bunyan\nbuildomat-client             /client\nbuildomat-common             /common\nbuildomat-database           /database\nbuildomat-server             /server\nbuildomat-types              /types\n\nbuildomat-factory-aws        /factory/aws\nbuildomat-factory-lab        /factory/lab\n\nbuildomat-github-common      /github/common\nbuildomat-github-database    /github/database\nbuildomat-github-dbtool      /github/dbtool\nbuildomat-github-ghtool      /github/ghtool\nbuildomat-github-server      /github/server\n\nxtask                        /xtask\n```\n\n### Buildomat Core\n\nThe buildomat core is responsible for authenticating users and remote services,\nfor managing build systems, and for running jobs and collecting output.\n\n#### Server (`buildomat-server`, in `server/`)\n\nThe core buildomat API server.  Coordinates the creation, tracking, and\ndestruction of workers in which to execute jobs.  This component sits at the\ncentre of the system and is used by the GitHub integration server, the client\ncommand, the agent running within each worker for control of the job, and any\nfactories.\n\n#### Client Command (`buildomat`, in `bin/`)\n\nA client tool that uses the client library to interface with and manipulate the\ncore server.  The tool has both administrative and user-level functions,\nexpressed in a relatively regular hierarchy of commands; e.g., `buildomat job\nrun` or `buildomat user ls`.\n\n```\n$ ./target/release/buildomat\nUsage: buildomat [OPTS] COMMAND [ARGS...]\n\nCommands:\n    info                get information about server and user account\n    control             server control functions\n    job                 job management\n    user                user management\n\n\nOptions:\n        --help          usage information\n    -p, --profile PROFILE\n                        authentication and server profile\n\nERROR: choose a command\n```\n\n#### Client Library (`buildomat-client`, in `client/`)\n\nA HTTP client library for accessing the core buildomat server.  This client is\ngenerated at build time by\n[`progenitor`](https://github.com/oxidecomputer/progenitor), an OpenAPI client\ngenerator.\n\nThe client is generated based an OpenAPI document managed in the repository and\ngenerated by Dropshot based on the implementation of the server and then\nchecked in to the repository.  If you make changes to the API exposed by the\ncore server, you will need to regenerate the document, `client/openapi.json`,\nusing:\n\n```\n$ cargo xtask openapi\n```\n\n#### Agent (`buildomat-agent`, in `agent`/)\n\nA process that is injected into an ephemeral AWS EC2 instance to allow the\nbuildomat core server to take control and run jobs.  This process receives\nsingle-use credentials at provisioning time from the core server, and connects\nout to receive instructions.  The agent does not require a public IP, or any\ndirect inbound connectivity, to allow agents to run inside remote NAT\nenvironments.\n\n### Factories\n\nBuildomat jobs are specified to execute within a particular target environment.\nConcrete instances of those target environments (known as _workers_) are\ncreated, managed, and destroyed by _factories_.  Factories are long-lived\nserver processes that connect to the core API and offer to construct workers as\nneeded.  When a worker has finished executing the job, or when requested by an\noperator, the factory is also responsible for freeing any resources that were\nin use by the worker.\n\n#### AWS Factory (`buildomat-factory-aws` in `factory/aws/`)\n\nThe AWS factory creates ephemeral AWS instances that are used to run one job\nand are then destroyed.  The factory arranges for the agent to be installed and\nstart automatically in each instance that is created.  The factory is\nresponsible for ensuring no stale resources are left behind, and for enforcing\na cap on the concurrent use of resources at AWS.  Each target provided by an\nAWS factory can support a different instance type (i.e., CPU and RAM capacity),\na different image (AMI), and a different root disk size.\n\n#### Lab Factory (`buildomat-factory-lab` in `factory/lab/`)\n\nThe lab factory uses IPMI to exert control over a set of physical lab systems.\nWhen a worker is required, a lab system is booted from a ramdisk and the agent\nis started, just as it would be for an AWS instance.  From that point on,\noperation is quite similar to AWS instances: the agent communicates directly\nwith the core API.  When tearing down a lab worker, the machine is rebooted\n(again via IPMI) to clear out the prior ramdisk state.  Each target provided by\na lab factory can boot from a different ramdisk image stored on a local server.\n\n### GitHub Integration (formerly known as Wollongong)\n\nThe GitHub-specific portion of the buildomat suite sits in front of the core\nbuildomat service.  It is responsible for receiving and processing\nnotifications of new commits and pull requests on GitHub, starting any\nconfigured build jobs, and reporting the results so that they are visible\nthrough the GitHub user interface.\n\n#### Server (`buildomat-github-server`, in `github/server/`)\n\nThis server acts as a [GitHub App](https://docs.github.com/en/developers/apps).\nIt is responsible for processing incoming [GitHub\nwebhooks](https://docs.github.com/en/developers/webhooks-and-events/webhooks/about-webhooks)\nthat notify the system about commits and pull requests in authorised\nrepositories.  In addition to relaying jobs between GitHub and the buildomat\ncore, this service provides an additional HTML presentation of job state (e.g.,\ndetailed logs) and access to any artefacts that jobs produce.  This server\nkeeps state required to manage the interaction with GitHub, but does not store\njob data; requests for logs or artefacts are proxied back to the core server.\n\n#### Database Tool (`buildomat-github-dbtool`, in `github/dbtool/`)\n\nThis tool can be used to inspect the database state kept by the GitHub\nintegration as it tracks GitHub pull requests and commits.  Unlike the core\nclient tool, this program directly interacts with a local SQLite database.\n\n```\n$ buildomat-github-dbtool\nUsage: buildomat-github-dbtool COMMAND [ARGS...]\n\nCommands:\n    delivery (del)      webhook deliveries\n    repository (repo)   GitHub repositories\n    check               GitHub checks\n\n\nOptions:\n    --help              usage information\n\nERROR: choose a command\n```\n\nOf particular note, the tool is useful for inspecting and replaying received\nwebhook events; e.g.,\n\n```\n$ buildomat-github-dbtool del ls\nSEQ   ACK RECVTIME             EVENT          ACTION\n0     1   2021-10-05T01:58:32Z ping           -\n1     1   2021-10-05T02:25:33Z installation   created\n2     1   2021-10-05T02:26:53Z push\n3     1   2021-10-05T02:26:53Z check_suite    requested\n4     1   2021-10-05T02:26:56Z check_suite    completed\n5     1   2021-10-05T02:26:56Z check_run      completed\n6     1   2021-10-05T02:26:56Z check_run      created\n7     1   2021-10-05T02:26:56Z check_run      created\n8     1   2021-10-05T02:26:57Z check_run      created\n...\n```\n\nThe `buildomat-github-dbtool del unack SEQ` command can be used to trigger the\nreprocessing of an invididual webhook message.\n\n## Per-repository Configuration\n\nBuildomat works as a [GitHub App](https://docs.github.com/en/developers/apps),\nwhich is generally \"installed\" at the level of an\n[Organisation](https://docs.github.com/en/organizations).  Installing the App\nallows buildomat to receive notifications about events, such as git pushes and\npull requests, from all repositories (public and private) within the\norganisation.  In order to avoid accidents, buildomat requires that the service\nbe explicitly configured for a repository before it will take any actions.\n\nPer-repository configuration is achieved by creating a file **in the default\nbranch** (e.g., `main`) of the repository in question, named\n`.github/buildomat/config.toml`.  This file is written in\n[TOML](https://toml.io/), with a handful of simple values.  Supported\nproperties in this file include:\n\n- `enable` **(boolean)**\n\n  Must be present and have the value `true` in order for buildomat to consider\n  the repository for jobs; e.g.,\n\n  ```toml\n  enable = true\n  ```\n\n- `org_only` **(boolean, defaults to `true` if missing)**\n\n  If set to `true`, or missing from the file, buildomat will not automatically\n  run jobs in response to pull requests opened by users that are not a member\n  of the GitHub Organisation which owns the repository.  If set to `false`, any\n  GitHub user can cause a job to be executed.\n\n  This property is important for security if your repository is able to create\n  any jobs that have access to secrets, or to restricted networks.\n\n- `allow_users` **(array of strings, each a GitHub login name)**\n\n  If specified, jobs will be started automatically for users in this list,\n  regardless of whether they are a member of the Organisation that owns the\n  repository or not, and regardless of the value of the `org_only` property.\n\n  This is often useful for pre-authorising jobs driven by Pull Requests\n  made by various automated systems; e.g.,\n\n  ```toml\n  allow_users = [\n          \"dependabot[bot]\",\n          \"renovate[bot]\",\n  ]\n  ```\n\nNote that buildomat will only ever read this configuration file from the most\nrecent commit in the default branch of the repository, not from the contents of\nanother branch or pull request.  This is of particular importance for\nsecurity-sensitive properties like `org_only`, where the policy set by users\nwith full write access to the repository must not be overridden by changes from\npotentially untrusted users.  If a pull request with a malicious policy change\nis merged, it will then be in the default branch and active for subsequent pull\nrequests; maintainers must carefully review pull requests that change this\nfile.\n\n## Specifying Jobs\n\nOnce you have configured buildomat at the repository level, you can specify\nsome number of jobs to execute automatically in response to pushes and pull\nrequests.  While per-repository configuration is read from the default branch,\njobs are read from the commit under test.\n\nJobs are specified as `bash` programs with some configuration directives\nembedded in comments.  These job files must be named\n`.github/buildomat/jobs/*.sh`.  Unexpected additional files in\n`.github/buildomat/jobs` will result in an error.\n\nJob files should begin with an interpreter line, followed by TOML-formatted\nconfiguration prefixed with `#:` so that they will be identified as\nconfiguration by buildomat, but ignored by the shell.  For example, a minimal\njob that would just execute `uname -a`:\n\n```bash\n#!/bin/bash\n#:\n#: name = \"build\"\n#: variety = \"basic\"\n#:\nuname -a\n```\n\nThe minimum set of properties that must always appear in the TOML frontmatter\nis:\n\n- `name` **(string)**\n\n  Must be present in all jobs.  This name is used for at least two things: as\n  the name of the Check Run in the GitHub user interface, and when specifying\n  that some other job depends on this job.  The job name must be unique amongst\n  all jobs within the commit under test.\n\n  In general, it is probably best to keep these short, lower-case, and without\n  spaces.  It is conventional to use the same name for the job file and the\n  job, e.g., `name = \"build\"` in file `.github/buildomat/jobs/build.sh`.\n\n- `variety` **(string)**\n\n  To allow the system to evolve over time, a job must specify a _variety_,\n  which defines some things about the way a job executes and what additional\n  configuration options are required or available.\n\nThese properties are optional, but not variety-specific:\n\n- `enable` **(boolean)**\n\n  To exclude a particular job file from processing, set this to `false`.  If\n  not specified, this property defaults to `true`.  This allows a job to be\n  temporarily disabled without needing to be removed from the repository.\n\nThe rest of the configuration is variety-specific.\n\n### Variety: Basic\n\nEach **basic** variety job (selected by specifying `variety = \"basic\"` in the\nfrontmatter) takes a single `bash` program and runs it in an ephemeral\nenvironment.  The composition of that environment, such as compute and memory\ncapacity or the availability of specific toolchains and other software, depends\non the `target` option.\n\nBasic variety jobs can produce output files (see the configuration options\n`output_rules` and `publish`).  They can also depend on the successful\ncompletion of other jobs, gaining access to any output files from the upstream\njob (see the `dependencies` option).  Jobs are generally executed in parallel,\nunless they are waiting for a dependency or for capacity to become available.\n\n#### Execution Environment\n\nBy default, an ephemeral system (generally a virtual machine) will be\nprovisioned for each job.  The system will be discarded at the end of the job,\nso no detritus is left behind.  Once the environment is provisioned, the `bash`\nprogram in the job file is executed as-is.\n\nJobs are executed as an unprivileged user, `build`, with home directory\n`/home/build`.  If required, this user is able to escalate to `root` privileges\nthrough the use of [pfexec(1)](https://illumos.org/man/1/pfexec).  Systems that\ndo not have a native `pfexec` will be furnished with a compatible wrapper\naround a native escalation facility, to ease the construction of cross-platform\njobs.\n\nBy default, the working directory for the job is based on the name of the\nrepository; e.g., for https://github.com/oxidecomputer/buildomat, the working\ndirectory would be `/work/oxidecomputer/buildomat`.  The system will arrange\nfor the repository to be cloned at that location with the commit under test\nchecked out.  A simple job could directly invoke some build tool like `gmake`\nor `cargo build`, and the build would occur at the root of the clone.  The\n`skip_clone` configuration option can disable this behaviour.\n\nMost targets provide toolchains from common metapackages like\n`build-essential`; e.g., `gmake` and `gcc`.  If a Rust toolchain is required,\none can be requested through the `rust_toolchain` configuration option.  This\nwill be installed using [rustup](https://rustup.rs/).\n\n##### Environment Variables\n\nWhile the complete set of environment variables is generally target-specific,\nthe common minimum for all targets includes:\n\n- `BUILDOMAT_JOB_ID` will be set to the unique ID of this job\n- `CI` will be set to `true`\n- `GITHUB_REPOSITORY` set to `owner/repository`; e.g., `oxidecomputer/buildomat`\n- `GITHUB_SHA` set to the commit ID of the commit under test\n- If the commit under test is part of a branch, then `GITHUB_BRANCH` will be\n  set to the branch name (e.g., `main`) and `GITHUB_REF` will be set to the ref\n  name; e.g., `res/heads/main`.\n- `HOME`, set to the home directory of the build user\n- `USER` and `LOGNAME`, set to the username of the build user\n- `PATH` set to include relevant directories for toolchains and other\n  useful software\n- `TZ` will be set to `UTC`\n- `LANG` and `LC_ALL` will be set to `en_US.UTF-8`\n\n##### Available Commands\n\nCross-platform shell programming can be challenging due to differences between\ndifferent operating systems.  To make this a little easier, we ensure that each\nbuildomat target can provide a basic suite of tools that are helpful in\nconstructing succint jobs:\n\n- [pfexec(1)](https://illumos.org/man/1/pfexec) allows escalation from the\n  unprivileged build user to `root`; e.g., `pfexec id -a`.\n- [ptime(1)](https://illumos.org/man/1/ptime) runs a program and provides\n  (with `-m`, detailed) timing information; e.g., `ptime -m cargo test`.\n- [banner(1)](https://illumos.org/man/1/banner) prints its arguments in\n  large letters on standard output, and is useful for producing headings\n  in job log output; e.g., `banner testing`.\n\n#### Configuration\n\nConfiguration properties supported for basic jobs include:\n\n- `access_repos` **(array of strings)**\n\n  Jobs can be created in both public and private repositories.  Public\n  repositories are available to everybody, but private repositories require\n  appropriate credentials.  By default, an ephemeral, read-only token is\n  injected into the execution environment (in the `$HOME/.netrc` file) that is\n  able to access only the repository directly under test.\n\n  If a job requires access to additional private repositories beyond the\n  direct repository, they may be specified in this list, in the form\n  `owner/repository`; e.g.,\n\n  ```bash\n  #: access_repos = [\n  #:\t\"oxidecomputer/clandestine-project\",\n  #:\t\"oxidecomputer/secret-plans\",\n  #: ]\n  ```\n\n  Note that this option only works for repositories within the same\n  organisation as the direct repository.  Using the option will trigger a\n  requirement for job-level authorisation by a member of the organisation.\n\n- `dependencies` **(table)**\n\n  A job may depend on the successful completion of one or more other jobs from\n  the same commit under test.  If the dependency is cancelled or fails to\n  complete successfully for some other reason, that failure will be propagated\n  forward as a failure of this job.\n\n  Each entry in the dependencies table is itself a table with a name for the\n  dependency, and the following per-dependency properties:\n\n  * `job` **(string)**\n\n    Specifies the job that this job should wait on for execution.  The `job`\n    value must exactly match the `name` property of some other `basic` variety\n    job available in the same commit.\n\n  Any artefacts output by the job named in the dependency will be made\n  available automatically under `/input/$dependency` using the dependency\n  name.  For example, consider this dependency directive:\n\n  ```bash\n  #: [dependencies.otherjob]\n  #: job = \"the-other-job!\"\n  ```\n\n  If the job with the name `the-other-job!` produces an output file,\n  `/tmp/output.zip`, then it will be made available within this job as the file\n  `/input/otherjob/tmp/output.zip`.\n\n  Using this facility, one can easily split a job into a \"build\" phase that\n  runs under a target with access to toolchains, and one or more \"test\" phases\n  that can take the build output and run it in under another target that might\n  not have a toolchain or may have access to other resources that have limited\n  availability like test hardware.\n\n  Jobs can also depend on more than one other job, allowing a job to aggregate\n  artefacts from several other jobs together in one place.  This might be\n  useful when building binaries for more than one different OS, with a final\n  step that publishes multi-OS packages if all the other builds were\n  successful.\n\n  Cycles in the dependency graph are not allowed.\n\n- `output_rules` **(array of strings)**\n\n  Jobs may produce artefacts that we wish to survive beyond the lifetime of the\n  ephemeral build environment.  A job may specify one or more files for\n  preservation by the system; e.g., a build job may produce binaries or\n  packages that can then be downloaded and installed, or a test job may produce\n  JUnit XML files or other diagnostic logs that can be inspected by engineers.\n\n  The `output_rules` property is a list of `/`-anchored glob patterns that\n  match files in the ephemeral machine; e.g., `/tmp/*.txt` would match\n  `/tmp/something.txt` but not `/tmp/nothing.png`.  Like the shell, a single\n  asterisk (`*`) will not descend into a hierarchy of directories.  If you want\n  to match recursively, a double asterisk (`**`) pattern will match the current\n  directory or any directory under that directory, but not files.  You can\n  combine these to get a recursive match; e.g., `/tmp/**/*.txt` would match\n  `/tmp/a.txt`, `/tmp/dir/a.txt`, and `/tmp/dir/dir/a.txt`.\n\n  By default, it is not an error to specify a pattern that does not match any\n  files.  Provided the job is not cancelled, matching files are uploaded\n  whether the job program exits with a zero status (denoting success) or a\n  non-zero status (denoting failure).  These behaviours can be used to upload\n  diagnostic logs left behind by unexpected test failures that are cleaned up\n  on success; e.g.,\n\n  ```bash\n  #: output_rules = [\n  #:\t\"/tmp/test_output/*\",\n  #: ]\n  ```\n\n  If the success of a job _requires_ that a particular artefact is produced,\n  the `=` prefix may be used to signify \"this rule must match at least one\n  file\".  If the rule does not match at least one output file, the job is\n  marked as failed even if the job program otherwise succeeded.  This can be\n  used to make sure that, say, a release binary build job produces an archive\n  with the expected name; e.g.,\n\n  ```bash\n  #: output_rules = [\n  #:\t\"=/work/pkg/important.tar.gz\",\n  #:\t\"=/work/pkg/important.sha256.txt\",\n  #: ]\n  ```\n\n  By default, the system attempts to ensure that a job has not accidentally\n  left background processes running that continue to modify the output\n  artefacts.  If the size or modified time of a file changes while it is being\n  uploaded, the job will fail.  To relax this restriction, the `%` prefix may\n  be used to signify that \"this file is allowed to change while it is being\n  uploaded\".  The `%` prefix will also ignore a file that is completely removed\n  by a background process before it is able to be uploaded.  This is used to\n  make best effort uploads of diagnostic log files for background processes\n  which may continue running even though the job is nominally complete; e.g.,\n\n  ```bash\n  #: output_rules = [\n  #:\t\"%/var/svc/log/*.log\",\n  #: ]\n  ```\n\n  To exclude specific files from upload, the `!` prefix can be used to signify\n  that \"any file that matches this pattern should be ignored, even if it was\n  nominally included by another pattern\".  Order in the array is not important;\n  a match of any exclusion rule will prevent that file from behing uploaded.\n  For example, to upload anything left in `/tmp` except for pictures:\n\n  ```bash\n  #: output_rules = [\n  #:\t\"/tmp/*\",\n  #:\t\"!/tmp/*.jpg\",\n  #: ]\n  ```\n\n  The must-match (`=`) and allow-change (`%`) prefixes may be combined in a\n  single output rule.  The exclusion prefix (`!`) may not be combined with any\n  other prefix.  For example, to require at least one log file (which may still\n  be growing) that is not `big-and-useless.log`:\n\n  ```bash\n  #: output_rules = [\n  #:\t\"=%/tmp/*.log\",\n  #:\t\"!/tmp/big-and-useless.log\",\n  #: ]\n  ```\n\n- `publish` **(array of tables)**\n\n  Some jobs may wish to publish a specific subset of their output artefacts at\n  a predictable URL based on the commit ID of the commit under test, for\n  reference by other jobs from other repositories, or end user tools.\n\n  Each table in the `publish` array of tables must contain these properties:\n\n  * `from_output` **(string)**\n\n    Specify the full path of the output artefact to be published without using\n    any wildcard syntax.  The output rule that provides this artefact should be\n    specified using a must-match (`=`) prefix so that the job fails if it is\n    not produced.  Each publish entry can specify exactly one output artefact.\n\n  * `series` **(string)**\n\n    Specify a series name to group a set of uploads together.  This is useful\n    to group related files together in the URL space, even if they are produced\n    by several different jobs.  This value should be short and URL-safe.\n\n  * `name` **(string)**\n\n    Specify the publically visible name of this file, which must be unique\n    within the series for this commit for this repository.  This value should\n    be short and URL-safe.\n\n  Each file published this way will be available at a predictable URL of the\n  form:\n\n  ```\n  https://buildomat.eng.oxide.computer/public/file/OWNER/REPO/SERIES/VERSION/NAME\n  ```\n\n  The `VERSION` value is the commit ID (full SHA) of the commit under test, and\n  the `SERIES` and `NAME` come from the `publish` entry.\n\n  For example, if commit `e65aace9237833ec775253cfde97f59a0af5bc3d` from\n  repository `oxidecomputer/software` included this publish directive:\n\n  ```bash\n  #: [[publish]]\n  #: from_output = \"/work/important-packaged-files.tar.gz\"\n  #: series = \"packages\"\n  #: name = \"files.tar.gz\"\n  ```\n\n  A published file would be available at the URL:\n\n  ```\n  https://buildomat.eng.oxide.computer/public/file/oxidecomputer/software/packages/e65aace9237833ec775253cfde97f59a0af5bc3d/files.tar.gz\n  ```\n\n  Note that files published this way from private repositories will be\n  available without authentication.\n\n- `rust_toolchain` **(string or boolean)**\n\n  If specified, `rustup` will be installed in the environment and the nominated\n  toolchain will be available as the default toolchain.  Any toolchain\n  specification that `rustup` accepts should work here; e.g., something general\n  like `stable` or `nightly`, or a specific nightly date, like\n  `nightly-2022-04-27`.\n\n  ```bash\n  #: rust_toolchain = \"stable\"\n  ```\n\n  It is also possible to use the boolean value `true` here, at which point\n  the system will interpret the contents of the `rust-toolchain.toml` file\n  in the root of the repository to decide what to install.  The file must\n  contain a valid `channel` value, and may also contain a valid `profile`\n  value.  Neither the legacy (pre-TOML) file format, nor TOML files which\n  contain the `path` directive, are supported.\n\n  ```bash\n  #: rust_toolchain = true\n  ```\n\n- `skip_clone` **(boolean)**\n\n  By default, a basic job will clone the repository and check out the commit\n  under test.  The working directory for the job will be named for\n  the GitHub repository; e.g., for https://github.com/oxidecomputer/buildomat,\n  the directory would be `/work/oxidecomputer/buildomat`.\n\n  If this option is specifed with the value `true`, no clone will be performed.\n  The working directory for the job will be `/work` without subdirectories.\n  This is useful in targets that do not provide toolchains or `git`, or where\n  no source files from the repository (beyond the job program itself) are\n  required for correct execution.\n\n  ```bash\n  #: skip_clone = true\n  ```\n\n- `target` **(string)**\n\n  The target for a job, which specifies the composition of the execution\n  environment, can be specified by name.  Some targets (e.g., `lab`) are\n  privileged, and not available to all repositories.\n\n  The list of unrestricted targets available for all jobs includes:\n\n  - `helios-latest`; an illumos execution environment (Oxide Helios\n    distribution) running in an ephemeral virtual machine, with a reasonable\n    set of build tools.  32GB of RAM and 200GB of disk should be available.\n  - `omnios-r151038`; an illumos execution environment (OmniOS r151038 LTS)\n    running in an ephemeral virtual machine, with a reasonable set of build\n    tools.  32GB of RAM and 200GB of disk should be available.\n  - `ubuntu-18.04`, `ubuntu-20.04`, and `ubuntu-22.04`; an Ubuntu execution\n    environment running in an ephemeral virtual machine, with a reasonable set\n    of build tools.  32GB of RAM and 200GB of disk should be available.\n\n## Licence\n\nUnless otherwise noted, all components are licenced under the [Mozilla Public\nLicense Version 2.0](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidecomputer%2Fbuildomat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxidecomputer%2Fbuildomat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidecomputer%2Fbuildomat/lists"}