Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/buildomat/fetch-gh-artifacts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# Copyright Oxide Computer Company

set -o errexit
set -o pipefail
set -o xtrace

# We use `--netrc` in these calls in order to use the GitHub token Buildomat
# provides us. This is not strictly necessary for all APIs we use, _except_ the
# one to download artifacts. But using it for all calls keeps us from hitting
# rate limits!

API_BASE="https://api.github.com/repos/$GITHUB_REPOSITORY"

# Buildomat creates at most one check suite per commit per repository, but
# GitHub Actions will generally make several. We need to choose which run we
# care about, ideally picking the one most closely related to this Buildomat
# check suite. We first look for the most recently-created "push" run, but if
# none are found we fall back to the most recently-created "pull_request" run.
#
# We check 10 times with 30 second pauses in between; if we don't have a check
# run within about five minutes it'll probably never show up.
for attempt in {1..10}; do
runs=$(curl -sSfL --netrc "$API_BASE/actions/runs?head_sha=$GITHUB_SHA" \
| jq -r --arg name "$1" '
.workflow_runs
| sort_by(.created_at) | reverse
| .[] | select(.name == $name)
| {id: .id, event: .event}
')
for event in push pull_request; do
run_id=$(jq -r --arg event "$event" 'select(.event == $event) | .id' <<<"$runs" | head -n 1)
[[ -n "$run_id" ]] && break 2
done
sleep 30
done
if [[ -z "$run_id" ]]; then
echo >&2 "no check run found"
exit 1
fi

# Wait for the run to complete.
until [[ $(curl -sSfL --netrc "$API_BASE/actions/runs/$run_id" | jq -r .status) == completed ]]; do
sleep 60
done

# Get information about artifacts and download them.
artifacts=$(curl -sSfL --netrc "$API_BASE/actions/runs/$run_id/artifacts" \
| jq -r '.artifacts[] | {id: .id, name: .name}')
for artifact_id in $(jq -r '.id' <<<"$artifacts"); do
artifact_name=$(jq -r --argjson id "$artifact_id" 'select(.id == $id) | .name' <<<"$artifacts")
# Artifact names are not allowed to contain special filesystem characters:
# https://github.com/actions/upload-artifact/issues/22
curl -sSfL --netrc -o "$artifact_name.zip" \
"$API_BASE/actions/artifacts/$artifact_id/zip"
done
62 changes: 62 additions & 0 deletions .github/buildomat/jobs/macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash
#:
#: name = "macos"
#: variety = "basic"
#: target = "ubuntu-22.04"
#: output_rules = [
#: "=/work/macos-aarch64/dpd",
#: "=/work/macos-aarch64/dpd.sha256.txt",
#: "=/work/macos-aarch64/swadm",
#: "=/work/macos-aarch64/swadm.sha256.txt",
#: ]
#:
#: [[publish]]
#: series = "macos-aarch64"
#: name = "dpd"
#: from_output = "/work/macos-aarch64/dpd"
#:
#: [[publish]]
#: series = "macos-aarch64"
#: name = "dpd.sha256.txt"
#: from_output = "/work/macos-aarch64/dpd.sha256.txt"
#:
#: [[publish]]
#: series = "macos-aarch64"
#: name = "swadm"
#: from_output = "/work/macos-aarch64/swadm"
#:
#: [[publish]]
#: series = "macos-aarch64"
#: name = "swadm.sha256.txt"
#: from_output = "/work/macos-aarch64/swadm.sha256.txt"

set -o errexit
set -o pipefail
set -o xtrace

function digest {
shasum -a 256 "$1" | awk -F ' ' '{print $1}'
}

banner "packages"
sudo apt update
sudo apt install -y jq unzip

# Buildomat doesn't have macOS workers. Our workaround is to build in GitHub
# Actions and poll for that over here.
banner "fetch"
# Set a 40 minute timeout since buildomat's GitHub token lasts an hour.
#
# XXX This is definitely not great and it would be much better to only kick off
# the buildomat job once GHA is complete.
timeout 40m .github/buildomat/fetch-gh-artifacts.sh build-macos

banner "unpack"

staging=/work/staging
mkdir -p "${staging}"
unzip macos-aarch64.zip -d "${staging}"
for bin in dpd swadm; do
digest "${staging}/${bin}" > "${staging}/${bin}.sha256.txt"
done
mv "${staging}" /work/macos-aarch64
87 changes: 87 additions & 0 deletions .github/workflows/build-macos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: build-macos

on:
push:
pull_request:

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
build:
# TODO: An optimization we can do here is to skip duplicate
# push/pull_request runs on branches created in this repo, e.g.:
#
# if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
#
# But the fetch-gh-artifacts.sh script (which is copied verbatim from
# github.com/oxidecomputer/cockroach) doesn't handle skipped jobs at the
# moment. We should consider fixing both copies of the script.
#
# ---
#
# Use the oldest supported arm64 image to do this build. Building on a newer
# image risks binaries that fail on older versions of macOS.
runs-on: macos-15
# This must stay below the 40 minutes the macos buildomat job waits for this
# run. See the XXX in .github/buildomat/jobs/macos.sh.
timeout-minutes: 35
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: "0"
# Omicron downloads these binaries onto machines that may lack Homebrew's
# OpenSSL dylibs, so link it statically.
OPENSSL_STATIC: "1"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Build the tip of the PR, not the merge commit GitHub synthesizes, so
# that the artifact matches the buildomat commit.
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Report toolchain versions
run: |
cargo --version
rustc --version
- name: Find or install Homebrew OpenSSL
run: |
openssl_dir="$(brew --prefix openssl@3)"
if [[ ! -f "${openssl_dir}/lib/libssl.a" ]]; then
brew install openssl@3
fi
echo "OPENSSL_DIR=${openssl_dir}" >> "${GITHUB_ENV}"
- name: Build dpd and swadm
run: cargo build --release --locked --features=tofino_stub --bin dpd --bin swadm
- name: Check binaries
run: |
set -o nounset
for bin in dpd swadm; do
bin_path="target/release/${bin}"

archs="$(lipo -archs "${bin_path}")"
if [[ "${archs}" != "arm64" ]]; then
echo "::error::${bin} was built for '${archs}', expected 'arm64'"
exit 1
fi

linked="$(otool -L "${bin_path}")"
echo "${linked}"
non_system="$(awk 'NR > 1 && $1 !~ /^(\/usr\/lib\/|\/System\/Library\/)/ { print $1 }' <<<"${linked}")"
if [[ -n "${non_system}" ]]; then
echo "::error::${bin} links against non-system libraries that machines downloading it may not have: ${non_system//$'\n'/ }"
exit 1
fi

"${bin_path}" --help >/dev/null
done
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: macos-aarch64
path: |
target/release/dpd
target/release/swadm
if-no-files-found: error
Loading