Skip to content
Draft
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
111 changes: 111 additions & 0 deletions .github/workflows/packaging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: Linux packaging

permissions:
contents: read

on:
pull_request:
branches: [ main ]
paths:
- 'packaging/**'
- 'scripts/packaging/**'
- '.github/workflows/release.yml'
- '.github/workflows/packaging.yml'
workflow_dispatch:

env:
# Both images are pinned by digest (tag shown for humans only).
UBUNTU_IMAGE: ubuntu:24.04@sha256:a853f94d226358a79c740cfc7bce0c289748f3fe3488d921d038ccd752c61b60
ARCH_IMAGE: archlinux:base-devel@sha256:51dd3d24f7fba779e7c471caeee7804c50e8c134ad948e19685a1c83a42facc3

jobs:
deb:
name: Build and install .deb (${{ matrix.deb_arch }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- deb_arch: amd64
runner: ubuntu-latest
archive_arch: x86_64
sha_var: PINNED_SHA256_LINUX_X86_64
- deb_arch: arm64
runner: ubuntu-24.04-arm
archive_arch: arm64
sha_var: PINNED_SHA256_LINUX_ARM64
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Download pinned release archive
run: |
set -euo pipefail
source packaging/pinned_release.env
expected="${{ matrix.sha_var }}"
curl -fsSL -o archive.tar.gz \
"https://github.com/amberframework/amber_cli/releases/download/v${PINNED_VERSION}/amber_cli-linux-${{ matrix.archive_arch }}.tar.gz"
echo "${!expected} archive.tar.gz" | sha256sum -c -
echo "PINNED_VERSION=${PINNED_VERSION}" >> "$GITHUB_ENV"
echo "EXPECTED_SHA=${!expected}" >> "$GITHUB_ENV"

- name: Build .deb in an Ubuntu container
run: |
mkdir -p out
docker run --rm -v "$PWD:/w" -w /w "$UBUNTU_IMAGE" \
scripts/packaging/build_deb.sh "$PINNED_VERSION" "${{ matrix.deb_arch }}" archive.tar.gz "$EXPECTED_SHA" out

- name: Install and smoke test in a fresh Ubuntu container
run: |
docker run --rm -v "$PWD/out:/out:ro" "$UBUNTU_IMAGE" bash -euxc '
deb=/out/amber-cli_'"$PINNED_VERSION"'_${{ matrix.deb_arch }}.deb
dpkg-deb -I "$deb"
dpkg-deb -c "$deb"
dpkg -i "$deb"
test -x /usr/bin/amber
test -x /usr/bin/amber-lsp
amber --version | tee /tmp/version
grep -F "'"$PINNED_VERSION"'" /tmp/version
amber-lsp --help || true
dpkg -s amber-cli | grep -F "Recommends: crystal-alpha | crystal"
dpkg -r amber-cli
test ! -e /usr/bin/amber
'

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: debs-${{ matrix.deb_arch }}
path: out/*.deb

arch:
name: Build and install amber-cli-bin (Arch, x86_64)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: PKGBUILD pins agree with packaging/pinned_release.env
run: |
set -euo pipefail
source packaging/pinned_release.env
pkgbuild=packaging/arch/amber-cli-bin/PKGBUILD
grep -Fx "pkgver=${PINNED_VERSION}" "$pkgbuild"
grep -F "sha256sums_x86_64=('${PINNED_SHA256_LINUX_X86_64}')" "$pkgbuild"
grep -F "sha256sums_aarch64=('${PINNED_SHA256_LINUX_ARM64}')" "$pkgbuild"

- name: makepkg, pacman -U, and smoke test as a non-root builder
run: |
docker run --rm -v "$PWD/packaging/arch/amber-cli-bin:/src:ro" "$ARCH_IMAGE" bash -euxc '
useradd -m builder
cp -r /src /home/builder/pkg
chown -R builder /home/builder/pkg
cd /home/builder/pkg
# .SRCINFO must match the PKGBUILD
su builder -c "makepkg --printsrcinfo" | diff -u .SRCINFO -
# fails closed on any checksum mismatch
su builder -c "makepkg --noconfirm"
ls -l *.pkg.tar.*
pacman -U --noconfirm ./*.pkg.tar.zst
amber --version | tee /tmp/version
grep -F "$(sed -n "s/^pkgver=//p" PKGBUILD)" /tmp/version
amber-lsp --help || true
pacman -Qi amber-cli-bin
'
60 changes: 60 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,66 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

package-deb:
name: Build and attach .deb packages
needs: upload-assets
runs-on: ubuntu-latest
if: github.event_name == 'release'
env:
# Pinned by digest (tag shown for humans only).
UBUNTU_IMAGE: ubuntu:24.04@sha256:a853f94d226358a79c740cfc7bce0c289748f3fe3488d921d038ccd752c61b60

steps:
- name: Checkout code
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: ${{ github.event.release.tag_name }}

- name: Download Linux archives built by this run
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
path: artifacts
pattern: amber_cli-linux-*

- name: Build .deb packages from the exact release archives
run: |
set -euo pipefail
version="${{ github.event.release.tag_name }}"
version="${version#v}"
mkdir -p debs
for pair in x86_64:amd64 arm64:arm64; do
archive_arch="${pair%%:*}"; deb_arch="${pair##*:}"
dir="artifacts/amber_cli-linux-${archive_arch}"
# Same hash the build job published; mismatch fails closed.
expected="$(cut -d' ' -f1 "${dir}/amber_cli-linux-${archive_arch}.tar.gz.sha256")"
docker run --rm -v "$PWD:/w" -w /w "$UBUNTU_IMAGE" \
scripts/packaging/build_deb.sh "$version" "$deb_arch" \
"${dir}/amber_cli-linux-${archive_arch}.tar.gz" "$expected" debs
done
(cd debs && sha256sum ./*.deb | sed 's# \./# #' > SHA256SUMS && cat SHA256SUMS)

- name: Smoke test the amd64 .deb
run: |
version="${{ github.event.release.tag_name }}"
version="${version#v}"
docker run --rm -v "$PWD/debs:/debs:ro" "$UBUNTU_IMAGE" bash -euxc "
dpkg -i /debs/amber-cli_${version}_amd64.deb
amber --version
amber-lsp --help || true
"

- name: Attach .deb packages and SHA256SUMS to the release
uses: softprops/action-gh-release@c12583777ecdfd3be55c69cf75464299dc01057e # v3
with:
files: |
debs/amber-cli_*_amd64.deb
debs/amber-cli_*_arm64.deb
debs/SHA256SUMS
tag_name: ${{ github.event.release.tag_name }}
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

notify-homebrew:
name: Notify Homebrew Tap
needs: upload-assets
Expand Down
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ amber --version
On Linux, use `sha256sum -c` for the checksum. Prefix only the `install`
command with `sudo` if `/usr/local/bin` is not writable.

### Ubuntu and Debian (.deb)

Release `2.0.6` and later attach `amber-cli_<version>_amd64.deb` and
`amber-cli_<version>_arm64.deb` plus a `SHA256SUMS` file to the GitHub release
(the package job in `release.yml` builds them from the same static archives).
The package installs `/usr/bin/amber` and `/usr/bin/amber-lsp` and recommends
a Crystal compiler (`crystal-alpha` or `crystal`).

```bash
version=2.0.6
deb="amber-cli_${version}_amd64.deb" # or _arm64.deb
curl -fLO "https://github.com/amberframework/amber_cli/releases/download/v${version}/${deb}"
curl -fLO "https://github.com/amberframework/amber_cli/releases/download/v${version}/SHA256SUMS"
sha256sum --ignore-missing -c SHA256SUMS
sudo apt install "./${deb}"
amber --version
```

Coming soon: apt repo. Until a hosting location is chosen, install the
`.deb` directly as shown above. Only `.deb` files from releases published after
this packaging lands exist; `2.0.6` itself ships archives only.

### Arch Linux and Omarchy (pacman, AUR)

Omarchy is Arch-based, so the Arch package covers it. The `amber-cli-bin`
`PKGBUILD` in `packaging/arch/` installs the prebuilt static binaries with
pinned sha256 sums:

```bash
git clone https://github.com/amberframework/amber_cli
cd amber_cli/packaging/arch/amber-cli-bin
makepkg -si
amber --version
```

Coming soon: `yay -S amber-cli-bin` once the AUR package is published. See
`packaging/arch/README.md` for maintainer steps.

## Create and verify a web app

```bash
Expand Down
50 changes: 50 additions & 0 deletions packaging/arch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Arch Linux and Omarchy packaging

`amber-cli-bin/` is an AUR-style `PKGBUILD` that installs the prebuilt static
`amber` and `amber-lsp` binaries from a GitHub release (`x86_64` and
`aarch64`). Omarchy is Arch-based, so the same package works there.

## Install from a local checkout

```bash
cd packaging/arch/amber-cli-bin
makepkg -si # run as a normal user, not root
amber --version
```

Once published to the AUR: `yay -S amber-cli-bin`.

## Every pin lives in the PKGBUILD

Each source has a `sha256sums` entry. `makepkg` fails closed on a mismatch;
never run it with `--skipchecksums` or `SKIPINTEGRITY`.

## Bump to a new release

1. Set `pkgver` (and reset `pkgrel=1`) in `PKGBUILD`.
2. Download each release archive and the tagged `LICENSE`, hash them with
`sha256sum`, and compare the archive hashes with the release's published
`.sha256` files. Put the hashes in `sha256sums`, `sha256sums_x86_64`, and
`sha256sums_aarch64`.
3. Update `packaging/pinned_release.env` to the same version and hashes.
4. Regenerate `.SRCINFO`: `makepkg --printsrcinfo > .SRCINFO`.
5. Test in a clean Arch container as a non-root user (CI does this on every
pull request that touches `packaging/`).

## First AUR submission (maintainer only, manual)

1. Create an AUR account and add your SSH public key to it.
2. `git clone ssh://aur@aur.archlinux.org/amber-cli-bin.git`
3. Copy `PKGBUILD` and `.SRCINFO` into the clone.
4. `git add PKGBUILD .SRCINFO && git commit -m "Initial import: amber-cli-bin 2.0.6"`
5. `git push` (the AUR accepts the `master` branch).

For later releases, repeat steps 3 to 5 with the bumped files. Nothing in this
repository publishes to the AUR automatically.

## Not provided

A source-build `amber-cli` PKGBUILD is intentionally absent. A reproducible
source build needs the Crystal toolchain plus `shards install --frozen` with
hash-verified shards, and the release job already produces the static binaries
the `-bin` package repackages.
22 changes: 22 additions & 0 deletions packaging/arch/amber-cli-bin/.SRCINFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pkgbase = amber-cli-bin
pkgdesc = Amber V2 command-line tool and language server (prebuilt static binaries)
pkgver = 2.0.6
pkgrel = 1
url = https://github.com/amberframework/amber_cli
arch = x86_64
arch = aarch64
license = MIT
optdepends = crystal-alpha: Crystal compiler used to build generated apps
optdepends = crystal: Crystal compiler used to build generated apps
provides = amber-cli=2.0.6
conflicts = amber-cli
options = !strip
options = !debug
source = LICENSE-2.0.6::https://raw.githubusercontent.com/amberframework/amber_cli/v2.0.6/LICENSE
sha256sums = 8a859ceb1a659af317a2b597f9e763d9a63cc4392f01628c211d2a5a38d77a4a
source_x86_64 = amber_cli-2.0.6-linux-x86_64.tar.gz::https://github.com/amberframework/amber_cli/releases/download/v2.0.6/amber_cli-linux-x86_64.tar.gz
sha256sums_x86_64 = 74cb45729d8c1f208d678003a81017df4832f7dad38e9103ee17583feddd4f73
source_aarch64 = amber_cli-2.0.6-linux-arm64.tar.gz::https://github.com/amberframework/amber_cli/releases/download/v2.0.6/amber_cli-linux-arm64.tar.gz
sha256sums_aarch64 = 8b914f3cacf8432dee388af4973bb68984676314a8a0f162ac7b6a9040412ac0

pkgname = amber-cli-bin
25 changes: 25 additions & 0 deletions packaging/arch/amber-cli-bin/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Maintainer: Amber Framework <crimsonknightstudios@gmail.com>
pkgname=amber-cli-bin
pkgver=2.0.6
pkgrel=1
pkgdesc='Amber V2 command-line tool and language server (prebuilt static binaries)'
arch=('x86_64' 'aarch64')
url='https://github.com/amberframework/amber_cli'
license=('MIT')
optdepends=('crystal-alpha: Crystal compiler used to build generated apps'
'crystal: Crystal compiler used to build generated apps')
provides=("amber-cli=${pkgver}")
conflicts=('amber-cli')
options=('!strip' '!debug')
source=("LICENSE-${pkgver}::https://raw.githubusercontent.com/amberframework/amber_cli/v${pkgver}/LICENSE")
source_x86_64=("amber_cli-${pkgver}-linux-x86_64.tar.gz::https://github.com/amberframework/amber_cli/releases/download/v${pkgver}/amber_cli-linux-x86_64.tar.gz")
source_aarch64=("amber_cli-${pkgver}-linux-arm64.tar.gz::https://github.com/amberframework/amber_cli/releases/download/v${pkgver}/amber_cli-linux-arm64.tar.gz")
sha256sums=('8a859ceb1a659af317a2b597f9e763d9a63cc4392f01628c211d2a5a38d77a4a')
sha256sums_x86_64=('74cb45729d8c1f208d678003a81017df4832f7dad38e9103ee17583feddd4f73')
sha256sums_aarch64=('8b914f3cacf8432dee388af4973bb68984676314a8a0f162ac7b6a9040412ac0')

package() {
install -Dm755 amber "${pkgdir}/usr/bin/amber"
install -Dm755 amber-lsp "${pkgdir}/usr/bin/amber-lsp"
install -Dm644 "LICENSE-${pkgver}" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}
25 changes: 25 additions & 0 deletions packaging/deb/copyright
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: amber_cli
Upstream-Contact: The Amber Team
Source: https://github.com/amberframework/amber_cli

Files: *
Copyright: 2025 The Amber Team
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
6 changes: 6 additions & 0 deletions packaging/pinned_release.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Release whose published archives the PR packaging checks repackage.
# Every archive is verified against these sha256 values; a mismatch fails closed.
# Keep in sync with packaging/arch/amber-cli-bin/PKGBUILD (CI checks this).
PINNED_VERSION=2.0.6
PINNED_SHA256_LINUX_X86_64=74cb45729d8c1f208d678003a81017df4832f7dad38e9103ee17583feddd4f73
PINNED_SHA256_LINUX_ARM64=8b914f3cacf8432dee388af4973bb68984676314a8a0f162ac7b6a9040412ac0
Loading
Loading