Skip to content
Merged
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
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
.gitignore
*.md
dist
rust/target
28 changes: 28 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Workflows

Only the release related workflows are described here.

## Release artifacts

`release.yaml` runs on `v*.*.*` tags and uploads archives to the GitHub release. The Rust CLI is the primary implementation and the JavaScript CLI is published under an `adc_js_` prefix.

| Implementation | Archive name | Binary inside |
|---|---|---|
| Rust | `adc_<version>_<os>_<arch>.{tar.gz,zip}` | `adc` |
| Rust debug info | `adc_<version>_<os>_<arch>_debuginfo.{tar.gz,zip}` | `adc.debug` (Linux), `adc.dSYM` (macOS), `adc.pdb` (Windows) |
| JavaScript | `adc_js_<version>_<os>_<arch>.{tar.gz,zip}` | `adc` |

- `<os>` is `linux`, `darwin` or `windows`, `<arch>` is `amd64` or `arm64`.
- The version comes from the tag. The Linux job fails the release when the tag does not match `version` under `[workspace.package]` in `rust/Cargo.toml`, so bump that first.
- Pull requests with the `test/build` label build only the Rust archives and upload them as workflow artifacts.

### Linux glibc floor

- The Linux job builds inside `almalinux:8` (glibc 2.28) so the binary runs on any glibc 2.28 or newer system. The `Check glibc floor` step fails when the binary references a newer `GLIBC_*` symbol version, which can happen after a toolchain or dependency change.
- `adc-linux-smoke` runs the built binary in Debian 11, Debian 12, Ubuntu 22.04 and Ubuntu 24.04 containers for both architectures. It runs after the archives are uploaded, so a failure does not block the upload.
- The binary is not static. Alpine and other musl systems need a glibc compatibility layer, which is not a supported target.
- The Linux job uses a container, so it can only use the JavaScript actions and shell tools available in that image. Install extra tools in the `Install build dependencies` step.

## Docker images

`docker.yaml` builds the images described in [libs/tools/README.md](../../libs/tools/README.md#docker-images). It runs on pushes to `main`, tags and pull requests, but only pushes images on `push` events.
29 changes: 29 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
push: ${{ github.event_name == 'push' }}
platforms: linux/amd64,linux/arm64
file: libs/tools/src/docker/Dockerfile
job-name-prefix: rust
meta-images: |
docker.io/api7/adc
ghcr.io/api7/adc
Expand All @@ -38,3 +39,31 @@ jobs:
- registry: ghcr.io
username: '${{ github.actor }}'
password: '${{ secrets.GITHUB_TOKEN }}'

build-js:
uses: docker/github-builder/.github/workflows/build.yml@c4a1b216d96a8c85b45a9974b37857828274c808 # v1.13.0
permissions:
contents: read
packages: write
id-token: write
with:
output: image
push: ${{ github.event_name == 'push' }}
platforms: linux/amd64,linux/arm64
file: libs/tools/src/docker/Dockerfile.js
job-name-prefix: js
meta-images: |
docker.io/api7/adc
ghcr.io/api7/adc
meta-tags: |
type=semver,pattern={{version}}-js
Comment thread
bzp2010 marked this conversation as resolved.
Resolved
type=raw,value=dev-js,enable={{is_default_branch}}
meta-flavor: latest=false
secrets:
registry-auths: |
- registry: docker.io
username: '${{ secrets.DOCKER_USERNAME }}'
password: '${{ secrets.DOCKER_PASSWORD }}'
- registry: ghcr.io
username: '${{ github.actor }}'
password: '${{ secrets.GITHUB_TOKEN }}'
131 changes: 90 additions & 41 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
env:
NODE_VERSION: "24.16.0"
jobs:
adc:
adc-js:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions:
Expand Down Expand Up @@ -43,25 +43,25 @@ jobs:
run: |
mkdir -p release
mv ./node-binary/linux-amd64 ./adc
tar -czf release/adc_${{ env.RELEASE_VERSION }}_linux_amd64.tar.gz ./adc && rm -rf ./adc
tar -czf release/adc_js_${{ env.RELEASE_VERSION }}_linux_amd64.tar.gz ./adc && rm -rf ./adc
mv ./node-binary/linux-arm64 ./adc
tar -czf release/adc_${{ env.RELEASE_VERSION }}_linux_arm64.tar.gz ./adc && rm -rf ./adc
tar -czf release/adc_js_${{ env.RELEASE_VERSION }}_linux_arm64.tar.gz ./adc && rm -rf ./adc
mv ./node-binary/win-x64.exe ./adc.exe
zip -r release/adc_${{ env.RELEASE_VERSION }}_windows_amd64.zip ./adc.exe && rm -rf ./adc.exe
zip -r release/adc_js_${{ env.RELEASE_VERSION }}_windows_amd64.zip ./adc.exe && rm -rf ./adc.exe
mv ./node-binary/win-arm64.exe ./adc.exe
zip -r release/adc_${{ env.RELEASE_VERSION }}_windows_arm64.zip ./adc.exe && rm -rf ./adc.exe
zip -r release/adc_js_${{ env.RELEASE_VERSION }}_windows_arm64.zip ./adc.exe && rm -rf ./adc.exe

- name: Upload ADC to GitHub release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
release/adc_${{ env.RELEASE_VERSION }}_linux_amd64.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_linux_arm64.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_windows_amd64.zip
release/adc_${{ env.RELEASE_VERSION }}_windows_arm64.zip
release/adc_js_${{ env.RELEASE_VERSION }}_linux_amd64.tar.gz
release/adc_js_${{ env.RELEASE_VERSION }}_linux_arm64.tar.gz
release/adc_js_${{ env.RELEASE_VERSION }}_windows_amd64.zip
release/adc_js_${{ env.RELEASE_VERSION }}_windows_arm64.zip

adc-macos:
adc-js-macos:
if: startsWith(github.ref, 'refs/tags/')
runs-on: macos-26
permissions:
Expand Down Expand Up @@ -95,19 +95,19 @@ jobs:
run: |
mkdir release
mv ./node-binary/darwin-arm64 ./adc
tar -czf release/adc_${{ env.RELEASE_VERSION }}_darwin_arm64.tar.gz ./adc && rm -rf ./adc
tar -czf release/adc_js_${{ env.RELEASE_VERSION }}_darwin_arm64.tar.gz ./adc && rm -rf ./adc
mv ./node-binary/darwin-x64 ./adc
tar -czf release/adc_${{ env.RELEASE_VERSION }}_darwin_amd64.tar.gz ./adc && rm -rf ./adc
tar -czf release/adc_js_${{ env.RELEASE_VERSION }}_darwin_amd64.tar.gz ./adc && rm -rf ./adc

- name: Upload ADC to GitHub release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
release/adc_${{ env.RELEASE_VERSION }}_darwin_arm64.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_darwin_amd64.tar.gz
release/adc_js_${{ env.RELEASE_VERSION }}_darwin_arm64.tar.gz
release/adc_js_${{ env.RELEASE_VERSION }}_darwin_amd64.tar.gz

adc-rust-linux:
adc-linux:
if: startsWith(github.ref, 'refs/tags/') || contains(github.event.pull_request.labels.*.name, 'test/build')
strategy:
fail-fast: false
Expand All @@ -118,9 +118,15 @@ jobs:
- os: ubuntu-24.04-arm
arch: arm64
runs-on: ${{ matrix.os }}
# Built on EL8 so the binary only needs glibc 2.28 or newer at runtime.
container: almalinux:8
permissions:
contents: write
steps:
- name: Install build dependencies
run: |
dnf install -y gcc-toolset-12-gcc gcc-toolset-12-binutils make cmake perl git tar gzip curl
echo "/opt/rh/gcc-toolset-12/root/usr/bin" >> $GITHUB_PATH
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
Expand All @@ -132,10 +138,19 @@ jobs:
echo "RELEASE_VERSION=pr-${{ github.event.pull_request.number }}" >> $GITHUB_ENV
fi

- name: Verify tag matches Cargo version
if: startsWith(github.ref, 'refs/tags/')
run: |
CARGO_VERSION=$(sed -n '/^\[workspace.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' rust/Cargo.toml)
if [ "$CARGO_VERSION" != "$RELEASE_VERSION" ]; then
echo "Tag version $RELEASE_VERSION does not match rust/Cargo.toml version $CARGO_VERSION"
exit 1
fi

- name: Setup Rust toolchain
run: |
rustup update stable
rustup default stable
curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
workspaces: rust -> target
Expand All @@ -144,6 +159,15 @@ jobs:
working-directory: ./rust
run: cargo build --release -p adc-cli

- name: Check glibc floor
run: |
MAX=$(objdump -T rust/target/release/adc | grep -o 'GLIBC_[0-9.]*' | sort -uV | tail -1)
echo "Highest required glibc symbol version: $MAX"
if [ "$(printf '%s\n' "$MAX" GLIBC_2.28 | sort -V | tail -1)" != "GLIBC_2.28" ]; then
echo "Binary requires $MAX, which is newer than the supported GLIBC_2.28"
exit 1
fi

- name: Split debug info
run: |
BIN_DIR=rust/target/release
Expand All @@ -155,28 +179,53 @@ jobs:
run: |
mkdir -p release
BIN_DIR=rust/target/release
tar -czf release/adc_rust_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}.tar.gz -C "$BIN_DIR" adc
tar -czf release/adc_rust_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}_debuginfo.tar.gz -C "$BIN_DIR" adc.debug
tar -czf release/adc_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}.tar.gz -C "$BIN_DIR" adc
tar -czf release/adc_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}_debuginfo.tar.gz -C "$BIN_DIR" adc.debug

- name: Upload adc to GitHub release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
release/adc_rust_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}.tar.gz
release/adc_rust_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}_debuginfo.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}_debuginfo.tar.gz

- name: Upload adc artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: github.event_name == 'pull_request'
with:
name: adc_rust_linux_${{ matrix.arch }}
name: adc_linux_${{ matrix.arch }}
path: |
release/adc_rust_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}.tar.gz
release/adc_rust_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}_debuginfo.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_linux_${{ matrix.arch }}_debuginfo.tar.gz
if-no-files-found: error

adc-rust-windows:
adc-linux-smoke:
needs: adc-linux
strategy:
fail-fast: false
matrix:
arch: [amd64, arm64]
image: ["debian:11", "debian:12", "ubuntu:22.04", "ubuntu:24.04"]
include:
- arch: amd64
os: ubuntu-latest
- arch: arm64
os: ubuntu-24.04-arm
runs-on: ${{ matrix.os }}
permissions:
contents: read
steps:
- name: Download adc artifact
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: adc_linux_${{ matrix.arch }}
- name: Run adc in ${{ matrix.image }}
run: |
mkdir bin
tar -xzf adc_*_linux_${{ matrix.arch }}.tar.gz -C bin
docker run --rm -v "$PWD/bin:/opt/adc:ro" ${{ matrix.image }} sh -c '/opt/adc/adc --version && /opt/adc/adc --help > /dev/null'

adc-windows:
if: startsWith(github.ref, 'refs/tags/') || contains(github.event.pull_request.labels.*.name, 'test/build')
strategy:
fail-fast: false
Expand Down Expand Up @@ -220,28 +269,28 @@ jobs:
run: |
New-Item -ItemType Directory -Force -Path release | Out-Null
$binDir = "rust/target/release"
Compress-Archive -Path "$binDir/adc.exe" -DestinationPath "release/adc_rust_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}.zip"
Compress-Archive -Path "$binDir/adc.pdb" -DestinationPath "release/adc_rust_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}_debuginfo.zip"
Compress-Archive -Path "$binDir/adc.exe" -DestinationPath "release/adc_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}.zip"
Compress-Archive -Path "$binDir/adc.pdb" -DestinationPath "release/adc_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}_debuginfo.zip"

- name: Upload adc to GitHub release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
release/adc_rust_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}.zip
release/adc_rust_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}_debuginfo.zip
release/adc_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}.zip
release/adc_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}_debuginfo.zip

- name: Upload adc artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: github.event_name == 'pull_request'
with:
name: adc_rust_windows_${{ matrix.arch }}
name: adc_windows_${{ matrix.arch }}
path: |
release/adc_rust_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}.zip
release/adc_rust_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}_debuginfo.zip
release/adc_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}.zip
release/adc_${{ env.RELEASE_VERSION }}_windows_${{ matrix.arch }}_debuginfo.zip
if-no-files-found: error

adc-rust-macos:
adc-macos:
if: startsWith(github.ref, 'refs/tags/') || contains(github.event.pull_request.labels.*.name, 'test/build')
strategy:
fail-fast: false
Expand Down Expand Up @@ -288,23 +337,23 @@ jobs:
run: |
mkdir -p release
BIN_DIR=rust/target/${{ matrix.target }}/release
tar -czf release/adc_rust_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}.tar.gz -C "$BIN_DIR" adc
tar -czf release/adc_rust_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}_debuginfo.tar.gz -C "$BIN_DIR" adc.dSYM
tar -czf release/adc_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}.tar.gz -C "$BIN_DIR" adc
tar -czf release/adc_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}_debuginfo.tar.gz -C "$BIN_DIR" adc.dSYM

- name: Upload adc to GitHub release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
release/adc_rust_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}.tar.gz
release/adc_rust_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}_debuginfo.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}_debuginfo.tar.gz

- name: Upload adc artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: github.event_name == 'pull_request'
with:
name: adc_rust_darwin_${{ matrix.arch }}
name: adc_darwin_${{ matrix.arch }}
path: |
release/adc_rust_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}.tar.gz
release/adc_rust_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}_debuginfo.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}.tar.gz
release/adc_${{ env.RELEASE_VERSION }}_darwin_${{ matrix.arch }}_debuginfo.tar.gz
if-no-files-found: error
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Or, you can download the appropriate binary from the [releases page](https://git

Pre-built binaries for `amd64` and `arm64` on Linux, Windows, and macOS are available now.

The binaries and the Docker images (`api7/adc:<version>`, also published to `ghcr.io/api7/adc`) are the Rust implementation. The JavaScript implementation is published as `adc_js_<version>_<os>_<arch>` archives and `api7/adc:<version>-js` images. The Linux binaries require glibc 2.28 or newer. See [Workflows](.github/workflows/README.md) and [tools](libs/tools/README.md) for the release details.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

## Configure ADC

You can configure ADC through environment variables or command line flags. Run `adc help [command]` to see the available configuration options for a command.
Expand Down Expand Up @@ -106,7 +108,19 @@ See the [`docs/`](docs/README.md) folder for the CLI command reference, configur

## Development

To build ADC from source, [install Nx](https://nx.dev/getting-started/installation) and run:
### Rust CLI

The default `adc` binary is built with Cargo:

```bash
cd rust
cargo build --release -p adc-cli
./target/release/adc -h
```

### JavaScript CLI

To build the JavaScript implementation, [install Nx](https://nx.dev/getting-started/installation) and run:

```bash
pnpm install
Expand Down
23 changes: 23 additions & 0 deletions libs/tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# tools

Distribution assets that are not part of the CLI itself.

## Docker images

Both images are published to `docker.io/api7/adc` and `ghcr.io/api7/adc` by `.github/workflows/docker.yaml`, for `linux/amd64` and `linux/arm64`.

| Dockerfile | Implementation | Tags |
|---|---|---|
| `src/docker/Dockerfile` | Rust | `<version>`, `dev` |
| `src/docker/Dockerfile.js` | JavaScript | `<version>-js`, `dev-js` |

- The Rust image builds `adc-cli` in `rust:1-trixie` and runs it on `gcr.io/distroless/cc-debian13:nonroot`. The runtime image provides glibc, libgcc and CA certificates, so the binary must stay glibc based. Moving to a static musl binary would require changing the base image as well.
- The Docker build context is the repository root. `.dockerignore` excludes `rust/target` and `node_modules`, keep them excluded or the context becomes very large.
- The entrypoint of each image is the CLI binary itself, so arguments are passed straight to `adc`.

## Install script

`src/s3/install` is what `https://run.api7.ai/adc/install` serves. `.github/workflows/update-s3-and-cloudfront.yaml` syncs it to S3 on every merge to `main`, independent of any release tag.

- It downloads `adc_<version>_<os>_<arch>.tar.gz` from the GitHub release, which is the Rust build. The file names are defined in [.github/workflows/README.md](../../.github/workflows/README.md#release-artifacts), keep both in step.
- The architecture mapping only converts `x86_64` to `amd64`. On Linux arm64 `uname -m` reports `aarch64`, which is not mapped.
Loading
Loading