mirror of
https://github.com/onyx-dot-app/onyx.git
synced 2026-10-22 11:22:49 -05:00
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2090 lines
87 KiB
YAML
2090 lines
87 KiB
YAML
name: Build and Push Docker Images on Tag
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "*"
|
|
workflow_dispatch:
|
|
|
|
# Set restrictive default permissions for all jobs. Jobs that need more permissions
|
|
# should explicitly declare them.
|
|
permissions:
|
|
# Required to checkout the repo on private repos (no-op on public)
|
|
contents: read
|
|
# Required for OIDC authentication with AWS
|
|
id-token: write # zizmor: ignore[excessive-permissions]
|
|
|
|
env:
|
|
EDGE_TAG: ${{ startsWith(github.ref_name, 'nightly-latest') || github.ref_name == 'edge' }}
|
|
|
|
jobs:
|
|
# Determine which components to build based on the tag
|
|
determine-builds:
|
|
# NOTE: Github-hosted runners have about 20s faster queue times and are preferred here.
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 90
|
|
outputs:
|
|
build-desktop: ${{ steps.check.outputs.build-desktop }}
|
|
build-web: ${{ steps.check.outputs.build-web }}
|
|
build-web-cloud: ${{ steps.check.outputs.build-web-cloud }}
|
|
build-backend: ${{ steps.check.outputs.build-backend }}
|
|
build-model-server: ${{ steps.check.outputs.build-model-server }}
|
|
is-cloud-tag: ${{ steps.check.outputs.is-cloud-tag }}
|
|
is-beta: ${{ steps.check.outputs.is-beta }}
|
|
is-beta-standalone: ${{ steps.check.outputs.is-beta-standalone }}
|
|
is-stable: ${{ steps.check.outputs.is-stable }}
|
|
is-latest: ${{ steps.check.outputs.is-latest }}
|
|
is-test-run: ${{ steps.check.outputs.is-test-run }}
|
|
sanitized-tag: ${{ steps.check.outputs.sanitized-tag }}
|
|
short-sha: ${{ steps.check.outputs.short-sha }}
|
|
steps:
|
|
- name: Checkout (for git tags)
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
with:
|
|
version: "0.11.25"
|
|
enable-cache: false
|
|
|
|
- name: Check which components to build and version info
|
|
id: check
|
|
env:
|
|
EVENT_NAME: ${{ github.event_name }}
|
|
run: |
|
|
set -eo pipefail
|
|
TAG="${GITHUB_REF_NAME}"
|
|
# Sanitize tag name by replacing slashes with hyphens (for Docker tag compatibility)
|
|
SANITIZED_TAG=$(echo "$TAG" | tr '/' '-')
|
|
SHORT_SHA="${GITHUB_SHA::7}"
|
|
|
|
# Initialize all flags to false
|
|
IS_CLOUD=false
|
|
IS_NIGHTLY=false
|
|
IS_VERSION_TAG=false
|
|
IS_STABLE=false
|
|
IS_BETA=false
|
|
IS_BETA_STANDALONE=false
|
|
IS_LATEST=false
|
|
IS_PROD_TAG=false
|
|
IS_TEST_RUN=false
|
|
BUILD_DESKTOP=false
|
|
BUILD_WEB=false
|
|
BUILD_WEB_CLOUD=false
|
|
BUILD_BACKEND=true
|
|
BUILD_MODEL_SERVER=true
|
|
|
|
# Determine tag type based on pattern matching (do regex checks once)
|
|
if [[ "$TAG" == *cloud* ]]; then
|
|
IS_CLOUD=true
|
|
fi
|
|
if [[ "$TAG" == nightly* ]]; then
|
|
IS_NIGHTLY=true
|
|
fi
|
|
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
|
IS_VERSION_TAG=true
|
|
fi
|
|
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
IS_STABLE=true
|
|
fi
|
|
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-beta(\.[0-9]+)?$ ]]; then
|
|
IS_BETA=true
|
|
fi
|
|
|
|
# Determine what to build based on tag type
|
|
if [[ "$IS_CLOUD" == "true" ]]; then
|
|
BUILD_WEB_CLOUD=true
|
|
else
|
|
BUILD_WEB=true
|
|
# Only build desktop for semver tags (excluding beta)
|
|
if [[ "$IS_VERSION_TAG" == "true" ]] && [[ "$IS_BETA" != "true" ]]; then
|
|
BUILD_DESKTOP=true
|
|
fi
|
|
fi
|
|
|
|
# Standalone version checks (for backend/model-server - version excluding cloud tags)
|
|
if [[ "$IS_BETA" == "true" ]] && [[ "$IS_CLOUD" != "true" ]]; then
|
|
IS_BETA_STANDALONE=true
|
|
fi
|
|
|
|
# Determine if this tag should get the "latest" Docker tag.
|
|
# Only the highest semver stable tag (vX.Y.Z exactly) gets "latest".
|
|
if [[ "$IS_STABLE" == "true" ]]; then
|
|
HIGHEST_STABLE=$(uv run --no-sync --with onyx-devtools ods latest-stable-tag) || {
|
|
echo "::error::Failed to determine highest stable tag via 'ods latest-stable-tag'"
|
|
exit 1
|
|
}
|
|
if [[ "$TAG" == "$HIGHEST_STABLE" ]]; then
|
|
IS_LATEST=true
|
|
fi
|
|
fi
|
|
|
|
# Determine if this is a production tag
|
|
# Production tags are: version tags (v1.2.3*) or nightly tags
|
|
if [[ "$IS_VERSION_TAG" == "true" ]] || [[ "$IS_NIGHTLY" == "true" ]]; then
|
|
IS_PROD_TAG=true
|
|
fi
|
|
|
|
# Determine if this is a test run (workflow_dispatch on non-production ref)
|
|
if [[ "$EVENT_NAME" == "workflow_dispatch" ]] && [[ "$IS_PROD_TAG" != "true" ]]; then
|
|
IS_TEST_RUN=true
|
|
fi
|
|
{
|
|
echo "build-desktop=$BUILD_DESKTOP"
|
|
echo "build-web=$BUILD_WEB"
|
|
echo "build-web-cloud=$BUILD_WEB_CLOUD"
|
|
echo "build-backend=$BUILD_BACKEND"
|
|
echo "build-model-server=$BUILD_MODEL_SERVER"
|
|
echo "is-cloud-tag=$IS_CLOUD"
|
|
echo "is-beta=$IS_BETA"
|
|
echo "is-beta-standalone=$IS_BETA_STANDALONE"
|
|
echo "is-stable=$IS_STABLE"
|
|
echo "is-latest=$IS_LATEST"
|
|
echo "is-test-run=$IS_TEST_RUN"
|
|
echo "sanitized-tag=$SANITIZED_TAG"
|
|
echo "short-sha=$SHORT_SHA"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
# Block the release when dependencies carry unignored critical vulnerabilities.
|
|
# Runs the same `ods audit` gate used on PRs and nightly. Always runs (no skip
|
|
# condition) so the build jobs that depend on it aren't skipped on test runs;
|
|
# the audit itself degrades gracefully when the S3 allowlist or Dependabot API
|
|
# is unavailable.
|
|
audit-gate:
|
|
needs: [determine-builds]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
permissions:
|
|
contents: read # checkout + read lockfiles
|
|
id-token: write # OIDC for fetching the S3 allowlist
|
|
security-events: read # read Dependabot alerts
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
with:
|
|
version: "0.11.25"
|
|
enable-cache: false
|
|
|
|
- name: Configure AWS credentials
|
|
continue-on-error: true # the audit still runs (with no suppressions) if creds are unavailable
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # ratchet:aws-actions/configure-aws-credentials@v6.2.0
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Run dependency audit
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: uv run --no-sync --with onyx-devtools ods audit --fail-on=critical
|
|
|
|
check-version-tag:
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 10
|
|
if: ${{ !startsWith(github.ref_name, 'nightly-latest') && github.ref_name != 'edge' && github.event_name != 'workflow_dispatch' }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
fetch-depth: 0
|
|
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
with:
|
|
version: "0.11.25"
|
|
# NOTE: This isn't caching much and zizmor suggests this could be poisoned, so disable.
|
|
enable-cache: false
|
|
|
|
- name: Validate tag is versioned correctly
|
|
run: |
|
|
uv run --no-sync --with release-tag tag --check
|
|
|
|
notify-slack-on-tag-check-failure:
|
|
needs:
|
|
- check-version-tag
|
|
if: always() && needs.check-version-tag.result == 'failure' && github.event_name != 'workflow_dispatch'
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 10
|
|
environment: release
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Send Slack notification
|
|
uses: ./.github/actions/slack-notify
|
|
with:
|
|
webhook-url: ${{ secrets.MONITOR_DEPLOYMENTS_WEBHOOK }}
|
|
failed-jobs: "• check-version-tag"
|
|
title: "🚨 Version Tag Check Failed"
|
|
ref-name: ${{ github.ref_name }}
|
|
|
|
# Create GitHub release first, before desktop builds start.
|
|
# This ensures all desktop matrix jobs upload to the same release instead of
|
|
# racing to create duplicate releases.
|
|
create-release:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-desktop == 'true'
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 10
|
|
permissions:
|
|
contents: write
|
|
outputs:
|
|
release-id: ${{ steps.create-release.outputs.id }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Determine release tag
|
|
id: release-tag
|
|
env:
|
|
IS_TEST_RUN: ${{ needs.determine-builds.outputs.is-test-run }}
|
|
SHORT_SHA: ${{ needs.determine-builds.outputs.short-sha }}
|
|
run: |
|
|
if [ "${IS_TEST_RUN}" == "true" ]; then
|
|
echo "tag=v0.0.0-dev+${SHORT_SHA}" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Create GitHub Release
|
|
id: create-release
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
TAG: ${{ steps.release-tag.outputs.tag }}
|
|
run: |
|
|
# Look up an existing release (including drafts) by tag name.
|
|
#
|
|
# NOTE: a draft release does not create the underlying git tag until
|
|
# it is published, so `GET /releases/tags/{tag}` (and
|
|
# `gh release view <tag>`) returns 404 for drafts. We must list
|
|
# releases instead — that endpoint DOES include drafts — and match
|
|
# on tag_name.
|
|
get_release_id() {
|
|
gh api --paginate "repos/${GITHUB_REPOSITORY}/releases" \
|
|
--jq ".[] | select(.tag_name == \"${TAG}\") | .id" | head -n1
|
|
}
|
|
|
|
release_id=$(get_release_id)
|
|
if [ -z "$release_id" ]; then
|
|
release_id=$(gh api --method POST "repos/${GITHUB_REPOSITORY}/releases" \
|
|
-f tag_name="$TAG" \
|
|
-f name="$TAG" \
|
|
-f body="See the assets to download this version and install." \
|
|
-F draft=true \
|
|
--jq '.id')
|
|
fi
|
|
|
|
if [ -z "$release_id" ]; then
|
|
echo "::error::Failed to resolve release id for tag ${TAG}"
|
|
exit 1
|
|
fi
|
|
echo "id=${release_id}" >> "$GITHUB_OUTPUT"
|
|
|
|
build-desktop:
|
|
needs:
|
|
- determine-builds
|
|
- create-release
|
|
if: needs.determine-builds.outputs.build-desktop == 'true'
|
|
permissions:
|
|
id-token: write
|
|
contents: write
|
|
actions: read
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- platform: "macos-latest" # Build a universal image for macOS.
|
|
args: "--target universal-apple-darwin"
|
|
rust-targets: "aarch64-apple-darwin,x86_64-apple-darwin"
|
|
- platform: "ubuntu-24.04"
|
|
args: "--bundles deb,rpm"
|
|
- platform: "ubuntu-24.04-arm" # Only available in public repos.
|
|
args: "--bundles deb,rpm"
|
|
- platform: "windows-latest"
|
|
args: ""
|
|
# Cross-compiled Windows ARM64 build. Only the NSIS bundle supports
|
|
# ARM64 (WiX/MSI does not), hence --bundles nsis.
|
|
- platform: "windows-latest"
|
|
args: "--target aarch64-pc-windows-msvc --bundles nsis"
|
|
rust-targets: "aarch64-pc-windows-msvc"
|
|
|
|
runs-on: ${{ matrix.platform }}
|
|
timeout-minutes: 90
|
|
environment: release
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v7.0.0
|
|
with:
|
|
# NOTE: persist-credentials is needed for tauri-action to upload assets to GitHub releases.
|
|
persist-credentials: true # zizmor: ignore[artipacked]
|
|
|
|
- name: Configure AWS credentials
|
|
if: startsWith(matrix.platform, 'macos-')
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
if: startsWith(matrix.platform, 'macos-')
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
APPLE_ID, deploy/apple-id
|
|
APPLE_PASSWORD, deploy/apple-password
|
|
APPLE_CERTIFICATE, deploy/apple-certificate
|
|
APPLE_CERTIFICATE_PASSWORD, deploy/apple-certificate-password
|
|
KEYCHAIN_PASSWORD, deploy/keychain-password
|
|
APPLE_TEAM_ID, deploy/apple-team-id
|
|
parse-json-secrets: true
|
|
|
|
- name: install dependencies (ubuntu only)
|
|
if: startsWith(matrix.platform, 'ubuntu-')
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
build-essential \
|
|
libglib2.0-dev \
|
|
libgirepository1.0-dev \
|
|
libgtk-3-dev \
|
|
libjavascriptcoregtk-4.1-dev \
|
|
libwebkit2gtk-4.1-dev \
|
|
libayatana-appindicator3-dev \
|
|
gobject-introspection \
|
|
pkg-config \
|
|
curl \
|
|
xdg-utils
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # ratchet:oven-sh/setup-bun@v2 # zizmor: ignore[cache-poisoning]
|
|
with:
|
|
bun-version: "1.3.13"
|
|
|
|
- name: install Rust stable
|
|
uses: dtolnay/rust-toolchain@6d9817901c499d6b02debbb57edb38d33daa680b # zizmor: ignore[impostor-commit]
|
|
with:
|
|
# Extra targets for jobs that cross-compile (macOS universal, Windows ARM64).
|
|
# Jobs building only for the host architecture leave this empty.
|
|
targets: ${{ matrix.rust-targets || '' }}
|
|
|
|
- name: install frontend dependencies
|
|
run: bun install --frozen-lockfile
|
|
|
|
- name: Inject version (Unix)
|
|
if: runner.os != 'Windows'
|
|
working-directory: ./desktop
|
|
env:
|
|
SHORT_SHA: ${{ needs.determine-builds.outputs.short-sha }}
|
|
IS_TEST_RUN: ${{ needs.determine-builds.outputs.is-test-run }}
|
|
run: |
|
|
if [ "${IS_TEST_RUN}" == "true" ]; then
|
|
VERSION="0.0.0-dev+${SHORT_SHA}"
|
|
else
|
|
VERSION="${GITHUB_REF_NAME#v}"
|
|
fi
|
|
echo "Injecting version: $VERSION"
|
|
|
|
# Update Cargo.toml
|
|
sed "s/^version = .*/version = \"$VERSION\"/" src-tauri/Cargo.toml > src-tauri/Cargo.toml.tmp
|
|
mv src-tauri/Cargo.toml.tmp src-tauri/Cargo.toml
|
|
|
|
# Update tauri.conf.json
|
|
jq --arg v "$VERSION" '.version = $v' src-tauri/tauri.conf.json > src-tauri/tauri.conf.json.tmp
|
|
mv src-tauri/tauri.conf.json.tmp src-tauri/tauri.conf.json
|
|
|
|
# Update package.json
|
|
jq --arg v "$VERSION" '.version = $v' package.json > package.json.tmp
|
|
mv package.json.tmp package.json
|
|
|
|
echo "Versions set to: $VERSION"
|
|
|
|
- name: Inject version (Windows)
|
|
if: runner.os == 'Windows'
|
|
working-directory: ./desktop
|
|
shell: pwsh
|
|
env:
|
|
IS_TEST_RUN: ${{ needs.determine-builds.outputs.is-test-run }}
|
|
run: |
|
|
# Windows MSI requires numeric-only build metadata, so we skip the SHA suffix
|
|
if ($env:IS_TEST_RUN -eq "true") {
|
|
$VERSION = "0.0.0"
|
|
} else {
|
|
# Strip 'v' prefix and any pre-release suffix (e.g., -beta.13) for MSI compatibility
|
|
$VERSION = "$env:GITHUB_REF_NAME" -replace '^v', '' -replace '-.*$', ''
|
|
}
|
|
Write-Host "Injecting version: $VERSION"
|
|
|
|
# Update Cargo.toml
|
|
$cargo = Get-Content src-tauri/Cargo.toml -Raw
|
|
$cargo = $cargo -replace '(?m)^version = .*', "version = `"$VERSION`""
|
|
Set-Content src-tauri/Cargo.toml $cargo -NoNewline
|
|
|
|
# Update tauri.conf.json
|
|
$json = Get-Content src-tauri/tauri.conf.json | ConvertFrom-Json
|
|
$json.version = $VERSION
|
|
$json | ConvertTo-Json -Depth 100 | Set-Content src-tauri/tauri.conf.json
|
|
|
|
# Update package.json
|
|
$pkg = Get-Content package.json | ConvertFrom-Json
|
|
$pkg.version = $VERSION
|
|
$pkg | ConvertTo-Json -Depth 100 | Set-Content package.json
|
|
|
|
Write-Host "Versions set to: $VERSION"
|
|
|
|
- name: Import Apple Developer Certificate
|
|
if: startsWith(matrix.platform, 'macos-')
|
|
run: |
|
|
echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12
|
|
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
|
security default-keychain -s build.keychain
|
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
|
security set-keychain-settings -t 3600 -u build.keychain
|
|
security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
|
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
|
|
security find-identity -v -p codesigning build.keychain
|
|
|
|
- name: Verify Certificate
|
|
if: startsWith(matrix.platform, 'macos-')
|
|
run: |
|
|
CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep -E "(Developer ID Application|Apple Distribution|Apple Development)" | head -n 1)
|
|
CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
|
|
echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV
|
|
echo "Certificate imported."
|
|
|
|
- uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # ratchet:tauri-apps/tauri-action@action-v0.6.2
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
APPLE_ID: ${{ env.APPLE_ID }}
|
|
APPLE_PASSWORD: ${{ env.APPLE_PASSWORD }}
|
|
APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }}
|
|
APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }}
|
|
with:
|
|
projectPath: desktop
|
|
# Use the release created by the create-release job to avoid race conditions
|
|
# when multiple matrix jobs try to create/update the same release simultaneously
|
|
releaseId: ${{ needs.create-release.outputs.release-id }}
|
|
assetNamePattern: "[name]_[arch][ext]"
|
|
args: ${{ matrix.args }}
|
|
|
|
build-web-amd64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-web == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=4cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-web-amd64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-web-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
# web/Dockerfile pulls its hardened Node base from dhi.io, authenticated with the same
|
|
# Docker account credentials (the account must have access to the DHI catalog).
|
|
- name: Login to Docker Hardened Images (dhi.io)
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
registry: dhi.io
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push AMD64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./web
|
|
file: ./web/Dockerfile
|
|
platforms: linux/amd64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
NODE_OPTIONS=--max-old-space-size=8192
|
|
cache-from: |
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:edge
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
build-web-arm64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-web == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=4cpu-linux-arm64
|
|
- run-id=${{ github.run_id }}-web-arm64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-web-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
# web/Dockerfile pulls its hardened Node base from dhi.io, authenticated with the same
|
|
# Docker account credentials (the account must have access to the DHI catalog).
|
|
- name: Login to Docker Hardened Images (dhi.io)
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
registry: dhi.io
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push ARM64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./web
|
|
file: ./web/Dockerfile
|
|
platforms: linux/arm64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
NODE_OPTIONS=--max-old-space-size=8192
|
|
cache-from: |
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:edge
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
merge-web:
|
|
needs:
|
|
- determine-builds
|
|
- build-web-amd64
|
|
- build-web-arm64
|
|
- image-audit
|
|
if: always() && needs.build-web-amd64.result == 'success' && needs.build-web-arm64.result == 'success' && needs.image-audit.result == 'success'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-merge-web
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-web-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
tags: |
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run == 'true' && format('web-{0}', needs.determine-builds.outputs.sanitized-tag) || github.ref_name }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-latest == 'true' && 'latest' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && env.EDGE_TAG == 'true' && 'edge' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-beta == 'true' && 'beta' || '' }}
|
|
type=semver,pattern={{version}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}}.{{minor}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
|
|
- name: Create and push manifest
|
|
env:
|
|
IMAGE_REPO: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
AMD64_DIGEST: ${{ needs.build-web-amd64.outputs.digest }}
|
|
ARM64_DIGEST: ${{ needs.build-web-arm64.outputs.digest }}
|
|
META_TAGS: ${{ steps.meta.outputs.tags }}
|
|
run: |
|
|
IMAGES="${IMAGE_REPO}@${AMD64_DIGEST} ${IMAGE_REPO}@${ARM64_DIGEST}"
|
|
docker buildx imagetools create \
|
|
$(printf '%s\n' "${META_TAGS}" | xargs -I {} echo -t {}) \
|
|
$IMAGES
|
|
|
|
build-web-cloud-amd64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-web-cloud == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=4cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-web-cloud-amd64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-web-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
# web/Dockerfile pulls its hardened Node base from dhi.io, authenticated with the same
|
|
# Docker account credentials (the account must have access to the DHI catalog).
|
|
- name: Login to Docker Hardened Images (dhi.io)
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
registry: dhi.io
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push AMD64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./web
|
|
file: ./web/Dockerfile
|
|
platforms: linux/amd64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
NEXT_PUBLIC_CLOUD_ENABLED=true
|
|
WEB_FRAME_PROTECTION_ENABLED=false
|
|
NEXT_PUBLIC_POSTHOG_KEY=${{ secrets.POSTHOG_KEY }}
|
|
NEXT_PUBLIC_POSTHOG_HOST=${{ secrets.POSTHOG_HOST }}
|
|
NEXT_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}
|
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${{ secrets.STRIPE_PUBLISHABLE_KEY }}
|
|
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=${{ vars.NEXT_PUBLIC_RECAPTCHA_SITE_KEY }}
|
|
NEXT_PUBLIC_GTM_ENABLED=true
|
|
NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=true
|
|
NEXT_PUBLIC_INCLUDE_ERROR_POPUP_SUPPORT_LINK=true
|
|
NODE_OPTIONS=--max-old-space-size=8192
|
|
SENTRY_RELEASE=${{ github.sha }}
|
|
secrets: |
|
|
sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
cache-from: type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
build-web-cloud-arm64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-web-cloud == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=4cpu-linux-arm64
|
|
- run-id=${{ github.run_id }}-web-cloud-arm64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-web-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
# web/Dockerfile pulls its hardened Node base from dhi.io, authenticated with the same
|
|
# Docker account credentials (the account must have access to the DHI catalog).
|
|
- name: Login to Docker Hardened Images (dhi.io)
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
registry: dhi.io
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push ARM64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./web
|
|
file: ./web/Dockerfile
|
|
platforms: linux/arm64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
NEXT_PUBLIC_CLOUD_ENABLED=true
|
|
WEB_FRAME_PROTECTION_ENABLED=false
|
|
NEXT_PUBLIC_POSTHOG_KEY=${{ secrets.POSTHOG_KEY }}
|
|
NEXT_PUBLIC_POSTHOG_HOST=${{ secrets.POSTHOG_HOST }}
|
|
NEXT_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}
|
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${{ secrets.STRIPE_PUBLISHABLE_KEY }}
|
|
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=${{ vars.NEXT_PUBLIC_RECAPTCHA_SITE_KEY }}
|
|
NEXT_PUBLIC_GTM_ENABLED=true
|
|
NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=true
|
|
NEXT_PUBLIC_INCLUDE_ERROR_POPUP_SUPPORT_LINK=true
|
|
NODE_OPTIONS=--max-old-space-size=8192
|
|
SENTRY_RELEASE=${{ github.sha }}
|
|
secrets: |
|
|
sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
cache-from: type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
merge-web-cloud:
|
|
needs:
|
|
- determine-builds
|
|
- build-web-cloud-amd64
|
|
- build-web-cloud-arm64
|
|
- image-audit
|
|
if: always() && needs.build-web-cloud-amd64.result == 'success' && needs.build-web-cloud-arm64.result == 'success' && needs.image-audit.result == 'success'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-merge-web-cloud
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-web-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
tags: |
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run == 'true' && format('web-cloud-{0}', needs.determine-builds.outputs.sanitized-tag) || github.ref_name }}
|
|
|
|
- name: Create and push manifest
|
|
env:
|
|
IMAGE_REPO: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
AMD64_DIGEST: ${{ needs.build-web-cloud-amd64.outputs.digest }}
|
|
ARM64_DIGEST: ${{ needs.build-web-cloud-arm64.outputs.digest }}
|
|
META_TAGS: ${{ steps.meta.outputs.tags }}
|
|
run: |
|
|
IMAGES="${IMAGE_REPO}@${AMD64_DIGEST} ${IMAGE_REPO}@${ARM64_DIGEST}"
|
|
docker buildx imagetools create \
|
|
$(printf '%s\n' "${META_TAGS}" | xargs -I {} echo -t {}) \
|
|
$IMAGES
|
|
|
|
build-backend-amd64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-backend == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-backend-amd64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-backend
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push AMD64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./backend
|
|
file: ./backend/Dockerfile
|
|
platforms: linux/amd64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
cache-from: |
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:edge
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
build-backend-arm64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-backend == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-arm64
|
|
- run-id=${{ github.run_id }}-backend-arm64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-backend
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push ARM64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./backend
|
|
file: ./backend/Dockerfile
|
|
platforms: linux/arm64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
cache-from: |
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:edge
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
merge-backend:
|
|
needs:
|
|
- determine-builds
|
|
- build-backend-amd64
|
|
- build-backend-arm64
|
|
- image-audit
|
|
if: always() && needs.build-backend-amd64.result == 'success' && needs.build-backend-arm64.result == 'success' && needs.image-audit.result == 'success'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-merge-backend
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-backend
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
tags: |
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run == 'true' && format('backend-{0}', needs.determine-builds.outputs.sanitized-tag) || github.ref_name }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-latest == 'true' && 'latest' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && env.EDGE_TAG == 'true' && 'edge' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-beta-standalone == 'true' && 'beta' || '' }}
|
|
type=semver,pattern={{version}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}}.{{minor}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
|
|
- name: Create and push manifest
|
|
env:
|
|
IMAGE_REPO: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
AMD64_DIGEST: ${{ needs.build-backend-amd64.outputs.digest }}
|
|
ARM64_DIGEST: ${{ needs.build-backend-arm64.outputs.digest }}
|
|
META_TAGS: ${{ steps.meta.outputs.tags }}
|
|
run: |
|
|
IMAGES="${IMAGE_REPO}@${AMD64_DIGEST} ${IMAGE_REPO}@${ARM64_DIGEST}"
|
|
docker buildx imagetools create \
|
|
$(printf '%s\n' "${META_TAGS}" | xargs -I {} echo -t {}) \
|
|
$IMAGES
|
|
|
|
build-model-server-amd64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-model-server == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-model-server-amd64
|
|
- volume=40gb
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-model-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
with:
|
|
buildkitd-flags: ${{ vars.DOCKER_DEBUG == 'true' && '--debug' || '' }}
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
# Dockerfile.model_server pulls its hardened Python base from dhi.io, authenticated
|
|
# with the same Docker account credentials (the account must have DHI catalog access).
|
|
- name: Login to Docker Hardened Images (dhi.io)
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
registry: dhi.io
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push AMD64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
env:
|
|
DEBUG: ${{ vars.DOCKER_DEBUG == 'true' && 1 || 0 }}
|
|
with:
|
|
context: ./backend
|
|
file: ./backend/Dockerfile.model_server
|
|
platforms: linux/amd64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
cache-from: |
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:edge
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ env.EDGE_TAG != 'true' && vars.MODEL_SERVER_NO_CACHE == 'true' }}
|
|
|
|
build-model-server-arm64:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.build-model-server == 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-arm64
|
|
- run-id=${{ github.run_id }}-model-server-arm64
|
|
- volume=40gb
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-model-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
with:
|
|
buildkitd-flags: ${{ vars.DOCKER_DEBUG == 'true' && '--debug' || '' }}
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
# Dockerfile.model_server pulls its hardened Python base from dhi.io, authenticated
|
|
# with the same Docker account credentials (the account must have DHI catalog access).
|
|
- name: Login to Docker Hardened Images (dhi.io)
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
registry: dhi.io
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push ARM64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
env:
|
|
DEBUG: ${{ vars.DOCKER_DEBUG == 'true' && 1 || 0 }}
|
|
with:
|
|
context: ./backend
|
|
file: ./backend/Dockerfile.model_server
|
|
platforms: linux/arm64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
ONYX_VERSION=${{ github.ref_name }}
|
|
cache-from: |
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:edge
|
|
type=registry,ref=${{ env.REGISTRY_IMAGE }}:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ env.EDGE_TAG != 'true' && vars.MODEL_SERVER_NO_CACHE == 'true' }}
|
|
|
|
merge-model-server:
|
|
needs:
|
|
- determine-builds
|
|
- build-model-server-amd64
|
|
- build-model-server-arm64
|
|
- image-audit
|
|
if: always() && needs.build-model-server-amd64.result == 'success' && needs.build-model-server-arm64.result == 'success' && needs.image-audit.result == 'success'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-merge-model-server
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/onyx-model-server
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
tags: |
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run == 'true' && format('model-server-{0}', needs.determine-builds.outputs.sanitized-tag) || github.ref_name }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-latest == 'true' && 'latest' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && env.EDGE_TAG == 'true' && 'edge' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-beta-standalone == 'true' && 'beta' || '' }}
|
|
type=semver,pattern={{version}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}}.{{minor}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
|
|
- name: Create and push manifest
|
|
env:
|
|
IMAGE_REPO: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
AMD64_DIGEST: ${{ needs.build-model-server-amd64.outputs.digest }}
|
|
ARM64_DIGEST: ${{ needs.build-model-server-arm64.outputs.digest }}
|
|
META_TAGS: ${{ steps.meta.outputs.tags }}
|
|
run: |
|
|
IMAGES="${IMAGE_REPO}@${AMD64_DIGEST} ${IMAGE_REPO}@${ARM64_DIGEST}"
|
|
docker buildx imagetools create \
|
|
$(printf '%s\n' "${META_TAGS}" | xargs -I {} echo -t {}) \
|
|
$IMAGES
|
|
|
|
prepare-sandbox:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
if: needs.determine-builds.outputs.is-test-run == 'true' || (needs.determine-builds.outputs.is-stable == 'true' || needs.determine-builds.outputs.is-beta-standalone == 'true' || needs.determine-builds.outputs.is-cloud-tag == 'true' || startsWith(github.ref_name, 'nightly-latest') || github.ref_name == 'edge')
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 10
|
|
environment: release
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
outputs:
|
|
context-tag: ${{ steps.context.outputs.context-tag }}
|
|
context-exists: ${{ steps.exists.outputs.context-exists }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/sandbox
|
|
SANDBOX_CONTEXT: backend/onyx/server/features/build/sandbox/image
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Compute sandbox context tag
|
|
id: context
|
|
run: |
|
|
set -euo pipefail
|
|
digest="$(git ls-files -s -z "$SANDBOX_CONTEXT" | sort -z | sha256sum | cut -d' ' -f1)"
|
|
echo "context-tag=ctx-${digest:0:20}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Configure AWS credentials
|
|
if: needs.determine-builds.outputs.is-test-run != 'true' && vars.DOCKER_NO_CACHE != 'true'
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
if: needs.determine-builds.outputs.is-test-run != 'true' && vars.DOCKER_NO_CACHE != 'true'
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Login to Docker Hub
|
|
if: needs.determine-builds.outputs.is-test-run != 'true' && vars.DOCKER_NO_CACHE != 'true'
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Check for existing context image
|
|
id: exists
|
|
env:
|
|
CONTEXT_TAG: ${{ steps.context.outputs.context-tag }}
|
|
DOCKER_NO_CACHE: ${{ vars.DOCKER_NO_CACHE == 'true' && 'true' || 'false' }}
|
|
IS_TEST_RUN: ${{ needs.determine-builds.outputs.is-test-run }}
|
|
run: |
|
|
if [ "${IS_TEST_RUN}" = "true" ] || [ "${DOCKER_NO_CACHE}" = "true" ]; then
|
|
echo "context-exists=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if docker buildx imagetools inspect "${REGISTRY_IMAGE}:${CONTEXT_TAG}" >/dev/null 2>&1; then
|
|
echo "context-exists=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "context-exists=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
build-sandbox-amd64:
|
|
needs:
|
|
- determine-builds
|
|
- prepare-sandbox
|
|
if: needs.prepare-sandbox.result == 'success' && needs.prepare-sandbox.outputs.context-exists != 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=4cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-sandbox-amd64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/sandbox
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push AMD64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./backend/onyx/server/features/build/sandbox/image
|
|
file: ./backend/onyx/server/features/build/sandbox/image/Dockerfile
|
|
platforms: linux/amd64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: |
|
|
type=registry,ref=${{ env.BASE_IMAGE_REGISTRY }}/onyxdotapp/sandbox:edge
|
|
type=registry,ref=${{ env.BASE_IMAGE_REGISTRY }}/onyxdotapp/sandbox:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
build-sandbox-arm64:
|
|
needs:
|
|
- determine-builds
|
|
- prepare-sandbox
|
|
if: needs.prepare-sandbox.result == 'success' && needs.prepare-sandbox.outputs.context-exists != 'true'
|
|
runs-on:
|
|
- runs-on
|
|
- runner=4cpu-linux-arm64
|
|
- run-id=${{ github.run_id }}-sandbox-arm64
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
outputs:
|
|
digest: ${{ steps.build.outputs.digest }}
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/sandbox
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Build and push ARM64
|
|
id: build
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
|
with:
|
|
context: ./backend/onyx/server/features/build/sandbox/image
|
|
file: ./backend/onyx/server/features/build/sandbox/image/Dockerfile
|
|
platforms: linux/arm64
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: |
|
|
type=registry,ref=${{ env.BASE_IMAGE_REGISTRY }}/onyxdotapp/sandbox:edge
|
|
type=registry,ref=${{ env.BASE_IMAGE_REGISTRY }}/onyxdotapp/sandbox:latest
|
|
cache-to: type=inline
|
|
outputs: type=image,name=${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
no-cache: ${{ vars.DOCKER_NO_CACHE == 'true' }}
|
|
|
|
merge-sandbox:
|
|
needs:
|
|
- determine-builds
|
|
- prepare-sandbox
|
|
- build-sandbox-amd64
|
|
- build-sandbox-arm64
|
|
- image-audit
|
|
if: always() && needs.prepare-sandbox.result == 'success' && needs.image-audit.result == 'success' && (needs.prepare-sandbox.outputs.context-exists == 'true' || (needs.build-sandbox-amd64.result == 'success' && needs.build-sandbox-arm64.result == 'success'))
|
|
runs-on:
|
|
- runs-on
|
|
- runner=2cpu-linux-x64
|
|
- run-id=${{ github.run_id }}-merge-sandbox
|
|
- extras=ecr-cache
|
|
timeout-minutes: 90
|
|
environment: release
|
|
permissions:
|
|
id-token: write
|
|
env:
|
|
REGISTRY_IMAGE: onyxdotapp/sandbox
|
|
steps:
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Get AWS Secrets
|
|
uses: aws-actions/aws-secretsmanager-get-secrets@2cb1a461cbd4865ac4299648312e4704c646cd53
|
|
with:
|
|
secret-ids: |
|
|
DOCKER_USERNAME, deploy/docker-username
|
|
DOCKER_TOKEN, deploy/docker-token
|
|
parse-json-secrets: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # ratchet:docker/setup-buildx-action@v4
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ env.DOCKER_USERNAME }}
|
|
password: ${{ env.DOCKER_TOKEN }}
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9
|
|
with:
|
|
images: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
flavor: |
|
|
latest=false
|
|
tags: |
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run == 'true' && format('sandbox-{0}', needs.determine-builds.outputs.sanitized-tag) || github.ref_name }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-latest == 'true' && 'latest' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && env.EDGE_TAG == 'true' && 'edge' || '' }}
|
|
type=raw,value=${{ needs.determine-builds.outputs.is-test-run != 'true' && needs.determine-builds.outputs.is-beta-standalone == 'true' && 'beta' || '' }}
|
|
type=semver,pattern={{version}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}}.{{minor}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
type=semver,pattern={{major}},enable=${{ needs.determine-builds.outputs.is-stable == 'true' }}
|
|
|
|
- name: Create and push manifest
|
|
env:
|
|
IMAGE_REPO: ${{ needs.determine-builds.outputs.is-test-run == 'true' && env.RUNS_ON_ECR_CACHE || env.REGISTRY_IMAGE }}
|
|
CONTEXT_TAG: ${{ needs.prepare-sandbox.outputs.context-tag }}
|
|
AMD64_DIGEST: ${{ needs.build-sandbox-amd64.outputs.digest }}
|
|
ARM64_DIGEST: ${{ needs.build-sandbox-arm64.outputs.digest }}
|
|
META_TAGS: ${{ steps.meta.outputs.tags }}
|
|
DOCKER_NO_CACHE: ${{ vars.DOCKER_NO_CACHE == 'true' && 'true' || 'false' }}
|
|
IS_TEST_RUN: ${{ needs.determine-builds.outputs.is-test-run }}
|
|
run: |
|
|
mapfile -t tags < <(printf '%s\n' "${META_TAGS}" | sed '/^$/d')
|
|
tag_args=()
|
|
for tag in "${tags[@]}"; do
|
|
tag_args+=("-t" "$tag")
|
|
done
|
|
|
|
if [[ "$IS_TEST_RUN" == "true" ]]; then
|
|
if [[ -z "$AMD64_DIGEST" || -z "$ARM64_DIGEST" ]]; then
|
|
echo "::error::Missing sandbox image digest(s); cannot create test manifest"
|
|
exit 1
|
|
fi
|
|
images="${IMAGE_REPO}@${AMD64_DIGEST} ${IMAGE_REPO}@${ARM64_DIGEST}"
|
|
docker buildx imagetools create \
|
|
"${tag_args[@]}" \
|
|
$images
|
|
elif [[ "$DOCKER_NO_CACHE" != "true" ]] && docker buildx imagetools inspect "${REGISTRY_IMAGE}:${CONTEXT_TAG}" >/dev/null 2>&1; then
|
|
docker buildx imagetools create \
|
|
"${tag_args[@]}" \
|
|
"${REGISTRY_IMAGE}:${CONTEXT_TAG}"
|
|
else
|
|
if [[ -z "$AMD64_DIGEST" || -z "$ARM64_DIGEST" ]]; then
|
|
echo "::error::Missing sandbox image digest(s); cannot create ${CONTEXT_TAG}"
|
|
exit 1
|
|
fi
|
|
tag_args=("-t" "${REGISTRY_IMAGE}:${CONTEXT_TAG}" "${tag_args[@]}")
|
|
images="${IMAGE_REPO}@${AMD64_DIGEST} ${IMAGE_REPO}@${ARM64_DIGEST}"
|
|
docker buildx imagetools create \
|
|
"${tag_args[@]}" \
|
|
$images
|
|
fi
|
|
|
|
dispatch-cloud-deployment:
|
|
needs:
|
|
- determine-builds
|
|
- merge-web-cloud
|
|
- merge-backend
|
|
- merge-model-server
|
|
- merge-sandbox
|
|
if: >-
|
|
always()
|
|
&& needs.merge-web-cloud.result == 'success'
|
|
&& needs.merge-backend.result == 'success'
|
|
&& needs.merge-model-server.result == 'success'
|
|
&& needs.merge-sandbox.result == 'success'
|
|
&& needs.determine-builds.outputs.is-cloud-tag == 'true'
|
|
&& needs.determine-builds.outputs.is-test-run != 'true'
|
|
# NOTE: Github-hosted runners have about 20s faster queue times and are preferred here.
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 10
|
|
permissions: {}
|
|
steps:
|
|
- name: Resolve dispatch target
|
|
id: target
|
|
env:
|
|
CLOUD_DEPLOYMENT_REPO: ${{ vars.CLOUD_DEPLOYMENT_REPO }}
|
|
run: |
|
|
if [ -z "$CLOUD_DEPLOYMENT_REPO" ]; then
|
|
echo "::error::CLOUD_DEPLOYMENT_REPO is not set"
|
|
exit 1
|
|
fi
|
|
echo "owner=${CLOUD_DEPLOYMENT_REPO%%/*}" >> "$GITHUB_OUTPUT"
|
|
echo "repo=${CLOUD_DEPLOYMENT_REPO#*/}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Mint GitHub App installation token
|
|
id: app-token
|
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1
|
|
with:
|
|
client-id: ${{ vars.CLOUD_DEPLOYMENT_APP_ID }}
|
|
private-key: ${{ secrets.CLOUD_DEPLOYMENT_APP_PRIVATE_KEY }}
|
|
# Scope the token to the same repo the dispatch targets, derived from CLOUD_DEPLOYMENT_REPO.
|
|
owner: ${{ steps.target.outputs.owner }}
|
|
repositories: ${{ steps.target.outputs.repo }}
|
|
permission-contents: write
|
|
|
|
- name: Trigger new-cloud-image dispatch
|
|
env:
|
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
CLOUD_DEPLOYMENT_REPO: ${{ vars.CLOUD_DEPLOYMENT_REPO }}
|
|
VERSION: ${{ github.ref_name }}
|
|
run: |
|
|
gh api "repos/${CLOUD_DEPLOYMENT_REPO}/dispatches" \
|
|
-f event_type=new-cloud-image \
|
|
-F "client_payload[version]=${VERSION}"
|
|
|
|
# Scan each freshly built image (amd64 digest) via `ods audit image`, reusing
|
|
# osv-scanner and the shared S3 allowlist from the dependency `audit-gate`.
|
|
# Runs before merge-* and every merge-* depends on it, so an unsuppressed
|
|
# CRITICAL blocks the public tags. SARIF goes to the Security tab regardless.
|
|
image-audit:
|
|
needs:
|
|
- determine-builds
|
|
- build-web-amd64
|
|
- build-web-cloud-amd64
|
|
- build-backend-amd64
|
|
- build-model-server-amd64
|
|
- build-sandbox-amd64
|
|
if: >-
|
|
always() && !cancelled() &&
|
|
(needs.build-web-amd64.result == 'success' ||
|
|
needs.build-web-cloud-amd64.result == 'success' ||
|
|
needs.build-backend-amd64.result == 'success' ||
|
|
needs.build-model-server-amd64.result == 'success' ||
|
|
needs.build-sandbox-amd64.result == 'success')
|
|
runs-on:
|
|
- runs-on
|
|
# amd64 to match the images scanned: `ods audit image` uses the docker CLI,
|
|
# which won't pull an amd64 image onto an arm64 host.
|
|
- runner=2cpu-linux-x64
|
|
# osv-scanner pulls the image and writes a full `docker save` tar (~2x its
|
|
# size); size the root volume up so large images don't fill the disk.
|
|
- volume=60gb
|
|
- run-id=${{ github.run_id }}-image-audit-${{ matrix.component }}
|
|
- extras=ecr-cache
|
|
permissions:
|
|
contents: read # checkout + uv project context
|
|
id-token: write # OIDC for fetching the S3 allowlist
|
|
security-events: write # SARIF uploads
|
|
timeout-minutes: 15
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- component: web
|
|
registry-image: onyxdotapp/onyx-web-server
|
|
- component: web-cloud
|
|
registry-image: onyxdotapp/onyx-web-server
|
|
- component: backend
|
|
registry-image: onyxdotapp/onyx-backend
|
|
- component: model-server
|
|
registry-image: onyxdotapp/onyx-model-server
|
|
- component: sandbox
|
|
registry-image: onyxdotapp/sandbox
|
|
steps:
|
|
- name: Check if this scan should run
|
|
id: should-run
|
|
run: |
|
|
case "$COMPONENT" in
|
|
web) RESULT="$BUILD_WEB" ;;
|
|
web-cloud) RESULT="$BUILD_WEB_CLOUD" ;;
|
|
backend) RESULT="$BUILD_BACKEND" ;;
|
|
model-server) RESULT="$BUILD_MODEL_SERVER" ;;
|
|
sandbox) RESULT="$BUILD_SANDBOX" ;;
|
|
esac
|
|
if [ "$RESULT" == "success" ]; then
|
|
echo "run=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "run=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
env:
|
|
COMPONENT: ${{ matrix.component }}
|
|
BUILD_WEB: ${{ needs.build-web-amd64.result }}
|
|
BUILD_WEB_CLOUD: ${{ needs.build-web-cloud-amd64.result }}
|
|
BUILD_BACKEND: ${{ needs.build-backend-amd64.result }}
|
|
BUILD_MODEL_SERVER: ${{ needs.build-model-server-amd64.result }}
|
|
BUILD_SANDBOX: ${{ needs.build-sandbox-amd64.result }}
|
|
|
|
- uses: runs-on/action@4e5f72399b6b17f2e79c511c1b38a315a64d22dc
|
|
if: steps.should-run.outputs.run == 'true'
|
|
|
|
- name: Checkout
|
|
if: steps.should-run.outputs.run == 'true'
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup uv
|
|
if: steps.should-run.outputs.run == 'true'
|
|
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
with:
|
|
version: "0.11.25"
|
|
enable-cache: false
|
|
|
|
- name: Configure AWS credentials
|
|
if: steps.should-run.outputs.run == 'true'
|
|
continue-on-error: true # the audit still runs (with no suppressions) if creds are unavailable
|
|
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # ratchet:aws-actions/configure-aws-credentials@v6.2.0
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
|
|
aws-region: us-east-2
|
|
|
|
- name: Login to Docker Hub
|
|
if: steps.should-run.outputs.run == 'true'
|
|
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4
|
|
with:
|
|
username: ${{ secrets.DOCKER_USERNAME }}
|
|
password: ${{ secrets.DOCKER_TOKEN }}
|
|
|
|
# Scan the by-digest image the build pushed, before merge-* tags it (same
|
|
# content in the ECR cache for test runs).
|
|
- name: Determine scan image
|
|
if: steps.should-run.outputs.run == 'true'
|
|
id: scan-image
|
|
run: |
|
|
case "$COMPONENT" in
|
|
web) DIGEST="$DIGEST_WEB" ;;
|
|
web-cloud) DIGEST="$DIGEST_WEB_CLOUD" ;;
|
|
backend) DIGEST="$DIGEST_BACKEND" ;;
|
|
model-server) DIGEST="$DIGEST_MODEL_SERVER" ;;
|
|
sandbox) DIGEST="$DIGEST_SANDBOX" ;;
|
|
esac
|
|
if [ "$IS_TEST_RUN" == "true" ]; then
|
|
echo "image=${RUNS_ON_ECR_CACHE}@${DIGEST}" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "image=docker.io/${REGISTRY_IMAGE}@${DIGEST}" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
env:
|
|
COMPONENT: ${{ matrix.component }}
|
|
IS_TEST_RUN: ${{ needs.determine-builds.outputs.is-test-run }}
|
|
REGISTRY_IMAGE: ${{ matrix.registry-image }}
|
|
DIGEST_WEB: ${{ needs.build-web-amd64.outputs.digest }}
|
|
DIGEST_WEB_CLOUD: ${{ needs.build-web-cloud-amd64.outputs.digest }}
|
|
DIGEST_BACKEND: ${{ needs.build-backend-amd64.outputs.digest }}
|
|
DIGEST_MODEL_SERVER: ${{ needs.build-model-server-amd64.outputs.digest }}
|
|
DIGEST_SANDBOX: ${{ needs.build-sandbox-amd64.outputs.digest }}
|
|
|
|
- name: Run image vulnerability audit
|
|
if: steps.should-run.outputs.run == 'true'
|
|
# Exits non-zero on unsuppressed CRITICAL (gates the release). --format
|
|
# writes SARIF to stdout (redirected to the file for the Security tab
|
|
# upload) and the human-readable report + runbook to stderr, so the CI log
|
|
# shows which advisories blocked and how to resolve/suppress them. On a
|
|
# hard scan failure nothing is written, so seed a valid empty SARIF to keep
|
|
# the always() upload below from choking.
|
|
run: |
|
|
uv run --no-sync --with onyx-devtools ods audit image "$IMAGE" \
|
|
--fail-on=critical --format=sarif,text > image-audit.sarif || status=$?
|
|
if [ ! -s image-audit.sarif ]; then
|
|
# $schema is a literal SARIF key, not a shell variable.
|
|
# shellcheck disable=SC2016
|
|
echo '{"$schema":"https://json.schemastore.org/sarif-2.1.0.json","version":"2.1.0","runs":[]}' > image-audit.sarif
|
|
fi
|
|
exit "${status:-0}"
|
|
env:
|
|
IMAGE: ${{ steps.scan-image.outputs.image }}
|
|
|
|
# Rolling main-HEAD builds (nightly-latest / edge) map to refs/heads/main so
|
|
# the Security tab stays authoritative for main and alerts auto-resolve on
|
|
# later main builds. Test runs (manual workflow_dispatch) upload against their
|
|
# own ref/sha instead, so the scan + upload can be verified without polluting
|
|
# main's alerts. Release/beta tags sit on older commits — they still gate, they
|
|
# just don't upload.
|
|
- name: Upload audit results to GitHub Security tab
|
|
if: >-
|
|
always() && steps.should-run.outputs.run == 'true' &&
|
|
((env.EDGE_TAG == 'true' && needs.determine-builds.outputs.is-test-run != 'true') ||
|
|
needs.determine-builds.outputs.is-test-run == 'true')
|
|
uses: github/codeql-action/upload-sarif@ba454b8ab46733eb6145342877cd148270bb77ab
|
|
with:
|
|
sarif_file: image-audit.sarif
|
|
category: image-audit-${{ matrix.component }}
|
|
ref: ${{ needs.determine-builds.outputs.is-test-run == 'true' && github.ref || 'refs/heads/main' }}
|
|
sha: ${{ github.sha }}
|
|
|
|
notify-slack-on-failure:
|
|
needs:
|
|
- determine-builds
|
|
- audit-gate
|
|
- create-release
|
|
- build-desktop
|
|
- build-web-amd64
|
|
- build-web-arm64
|
|
- merge-web
|
|
- build-web-cloud-amd64
|
|
- build-web-cloud-arm64
|
|
- merge-web-cloud
|
|
- build-backend-amd64
|
|
- build-backend-arm64
|
|
- merge-backend
|
|
- build-model-server-amd64
|
|
- build-model-server-arm64
|
|
- merge-model-server
|
|
- prepare-sandbox
|
|
- build-sandbox-amd64
|
|
- build-sandbox-arm64
|
|
- merge-sandbox
|
|
- image-audit
|
|
if: always() && (needs.audit-gate.result == 'failure' || needs.create-release.result == 'failure' || needs.build-desktop.result == 'failure' || needs.build-web-amd64.result == 'failure' || needs.build-web-arm64.result == 'failure' || needs.merge-web.result == 'failure' || needs.build-web-cloud-amd64.result == 'failure' || needs.build-web-cloud-arm64.result == 'failure' || needs.merge-web-cloud.result == 'failure' || needs.build-backend-amd64.result == 'failure' || needs.build-backend-arm64.result == 'failure' || needs.merge-backend.result == 'failure' || needs.build-model-server-amd64.result == 'failure' || needs.build-model-server-arm64.result == 'failure' || needs.merge-model-server.result == 'failure' || needs.prepare-sandbox.result == 'failure' || needs.build-sandbox-amd64.result == 'failure' || needs.build-sandbox-arm64.result == 'failure' || needs.merge-sandbox.result == 'failure' || needs.image-audit.result == 'failure') && needs.determine-builds.outputs.is-test-run != 'true'
|
|
# NOTE: Github-hosted runners have about 20s faster queue times and are preferred here.
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 90
|
|
environment: release
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Determine failed jobs
|
|
id: failed-jobs
|
|
shell: bash
|
|
run: |
|
|
FAILED_JOBS=""
|
|
if [ "${NEEDS_AUDIT_GATE_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• audit-gate\\n"
|
|
fi
|
|
if [ "${NEEDS_CREATE_RELEASE_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• create-release\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_DESKTOP_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-desktop\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_WEB_AMD64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-web-amd64\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_WEB_ARM64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-web-arm64\\n"
|
|
fi
|
|
if [ "${NEEDS_MERGE_WEB_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• merge-web\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_WEB_CLOUD_AMD64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-web-cloud-amd64\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_WEB_CLOUD_ARM64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-web-cloud-arm64\\n"
|
|
fi
|
|
if [ "${NEEDS_MERGE_WEB_CLOUD_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• merge-web-cloud\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_BACKEND_AMD64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-backend-amd64\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_BACKEND_ARM64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-backend-arm64\\n"
|
|
fi
|
|
if [ "${NEEDS_MERGE_BACKEND_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• merge-backend\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_MODEL_SERVER_AMD64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-model-server-amd64\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_MODEL_SERVER_ARM64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-model-server-arm64\\n"
|
|
fi
|
|
if [ "${NEEDS_MERGE_MODEL_SERVER_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• merge-model-server\\n"
|
|
fi
|
|
if [ "${NEEDS_PREPARE_SANDBOX_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• prepare-sandbox\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_SANDBOX_AMD64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-sandbox-amd64\\n"
|
|
fi
|
|
if [ "${NEEDS_BUILD_SANDBOX_ARM64_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• build-sandbox-arm64\\n"
|
|
fi
|
|
if [ "${NEEDS_MERGE_SANDBOX_RESULT}" == "failure" ]; then
|
|
FAILED_JOBS="${FAILED_JOBS}• merge-sandbox\\n"
|
|
fi
|
|
# Remove trailing \n and set output
|
|
FAILED_JOBS=$(printf '%s' "$FAILED_JOBS" | sed 's/\\n$//')
|
|
echo "jobs=$FAILED_JOBS" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
NEEDS_AUDIT_GATE_RESULT: ${{ needs.audit-gate.result }}
|
|
NEEDS_CREATE_RELEASE_RESULT: ${{ needs.create-release.result }}
|
|
NEEDS_BUILD_DESKTOP_RESULT: ${{ needs.build-desktop.result }}
|
|
NEEDS_BUILD_WEB_AMD64_RESULT: ${{ needs.build-web-amd64.result }}
|
|
NEEDS_BUILD_WEB_ARM64_RESULT: ${{ needs.build-web-arm64.result }}
|
|
NEEDS_MERGE_WEB_RESULT: ${{ needs.merge-web.result }}
|
|
NEEDS_BUILD_WEB_CLOUD_AMD64_RESULT: ${{ needs.build-web-cloud-amd64.result }}
|
|
NEEDS_BUILD_WEB_CLOUD_ARM64_RESULT: ${{ needs.build-web-cloud-arm64.result }}
|
|
NEEDS_MERGE_WEB_CLOUD_RESULT: ${{ needs.merge-web-cloud.result }}
|
|
NEEDS_BUILD_BACKEND_AMD64_RESULT: ${{ needs.build-backend-amd64.result }}
|
|
NEEDS_BUILD_BACKEND_ARM64_RESULT: ${{ needs.build-backend-arm64.result }}
|
|
NEEDS_MERGE_BACKEND_RESULT: ${{ needs.merge-backend.result }}
|
|
NEEDS_BUILD_MODEL_SERVER_AMD64_RESULT: ${{ needs.build-model-server-amd64.result }}
|
|
NEEDS_BUILD_MODEL_SERVER_ARM64_RESULT: ${{ needs.build-model-server-arm64.result }}
|
|
NEEDS_MERGE_MODEL_SERVER_RESULT: ${{ needs.merge-model-server.result }}
|
|
NEEDS_PREPARE_SANDBOX_RESULT: ${{ needs.prepare-sandbox.result }}
|
|
NEEDS_BUILD_SANDBOX_AMD64_RESULT: ${{ needs.build-sandbox-amd64.result }}
|
|
NEEDS_BUILD_SANDBOX_ARM64_RESULT: ${{ needs.build-sandbox-arm64.result }}
|
|
NEEDS_MERGE_SANDBOX_RESULT: ${{ needs.merge-sandbox.result }}
|
|
|
|
- name: Send Slack notification
|
|
uses: ./.github/actions/slack-notify
|
|
with:
|
|
webhook-url: ${{ secrets.MONITOR_DEPLOYMENTS_WEBHOOK }}
|
|
failed-jobs: ${{ steps.failed-jobs.outputs.jobs }}
|
|
title: "🚨 Deployment Workflow Failed"
|
|
ref-name: ${{ github.ref_name }}
|