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
66 changes: 66 additions & 0 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: pr-build

# Build, test, pack, and index every plugin in this repo WITHOUT publishing, so a pull request or a
# branch push gets a downloadable preview of exactly what would ship. Same pipeline as release, driven
# by the one reusable Bespok3d build Action (b3-builder) with publish: 'false': it still builds the bake
# payloads, packs the .b3 set, assembles the sub-list index, and runs each plugin's tests, but cuts no
# GitHub release and registers nothing in the main index. The produced .b3 (plus atoms and the assembled
# index.json) upload as a run artifact, downloadable from the PR's Checks tab and the Actions run page.
# Publishing stays main-only, in release.yml.
on:
pull_request:
push:
branches-ignore: [main]
paths:
- '*/manifest.json'
- '*/files/**'
- '*/doc/**'
- '*/src/**'
- '*/toolchain/**'
- '*/tests/**'
- .github/workflows/pr-build.yml

# A branch push and the pull_request for the same head would otherwise build twice; collapse them into
# one run per head branch and cancel a superseded build when a newer commit lands.
concurrency:
group: pr-build-${{ github.event.pull_request.head.ref || github.ref }}
cancel-in-progress: true

jobs:
pr-build:
runs-on: ubuntu-latest
permissions:
contents: read # checkout only, no release / index commit / registration
pull-requests: write # post a sticky comment linking the build artifact on the PR
steps:
- uses: actions/checkout@v4

- uses: Bespok3d/b3-builder@main
with:
unit: repo
bake: 'true'
publish: 'false'
atom-repo: ${{ github.repository }}
list-name: 'Reference Python Plugins'
list-publisher: 'PLACEHOLDER'
list-ref-name: 'Reference Python Plugins'

- uses: actions/upload-artifact@v4
id: upload
with:
name: b3-packages-${{ github.event.repository.name }}
path: |
dist/*.b3
dist/*.atom.json
dist/index.json
if-no-files-found: error

# Surface the build on the PR page, not only the Actions run: a sticky comment linking the
# downloadable artifact. Fires on pull_request events only; a plain branch push has no PR.
- name: link the artifact on the PR
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr comment "${{ github.event.pull_request.number }}" --edit-last --create-if-none \
--body "**b3-packages preview** (build only, not published). Download the packed \`.b3\` set, its atoms, and the assembled index: [b3-packages-${{ github.event.repository.name }}](${{ steps.upload.outputs.artifact-url }}). Rebuilt for commit \`${{ github.sha }}\`."
106 changes: 19 additions & 87 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
name: build-and-release

# On a push to main that changes a plugin or the build scripts: pack every plugin's .b3, publish a
# GitHub release per plugin, regenerate this repo's sub-list index.json, and register the sub-list in
# Bespok3d/main-index (a one-time-idempotent lists[] reference) so the official catalog picks it up.
# Each plugin's Python dependencies are baked into its .b3 first (ADR-0036), so the printer never runs
# pip: a requirements.txt becomes files/wheels/ (own-service venv) and a klipper_requirements.txt
# becomes files/site-packages/ (a Klipper/Moonraker extra). These deps are pure Python; a compiled
# dep would build its wheel on an arm64 runner first.
# Build, test, pack, release, index, and register every plugin in this repo through the one reusable
# Bespok3d build Action (b3-builder). This repo no longer carries its own build/pack/atom/list scripts in
# CI: the Action wraps the whole pipeline, so the only thing here is who this publisher is (org identity
# via the Action inputs) and the token to register the sub-list.
on:
push:
branches: [main]
paths:
- '*/manifest.json'
- '*/files/**'
- '*/doc/**'
- scripts/**
- '*/src/**'
- '*/toolchain/**'
- '*/tests/**'
- .github/workflows/release.yml
workflow_dispatch:

Expand All @@ -25,85 +24,18 @@ jobs:
contents: write # create releases + commit index.json on this repo
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
fetch-depth: 0 # full history so the index.json push can rebase on a concurrent update

- uses: actions/setup-python@v5
- uses: Bespok3d/b3-builder@main
with:
python-version: '3.11'

- name: Bake each plugin's Python deps into its files (ADR-0036)
run: sh scripts/bake-deps.sh

- name: Pack every plugin .b3
run: sh scripts/pack.sh

- name: Release each plugin and generate its atom
env:
GH_TOKEN: ${{ github.token }}
run: |
for dir in */; do
[ -f "${dir}manifest.json" ] || continue
id="${dir%/}"
name=$(jq -r '.name' "${dir}manifest.json")
version=$(jq -r '.version' "${dir}manifest.json")
tag="${name}-v${version}"
asset="${name}-${version}.b3"
if ! gh release view "$tag" >/dev/null 2>&1; then
gh release create "$tag" --title "$tag" --notes "Automated release of ${asset}"
fi
gh release upload "$tag" "dist/${asset}" --clobber
# The asset's API URL (.url, not browser_download_url) is what the app fetches with a
# bearer token + Accept: application/octet-stream (works for private repos).
download_url=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${tag}" \
--jq ".assets[] | select(.name==\"${asset}\") | .url")
node scripts/generate-atom.mjs --plugin "$id" --download-url "$download_url" --repo "$GITHUB_REPOSITORY"
done

- name: Assemble this repo's sub-list index.json
run: node scripts/assemble-list.mjs

- name: Commit index.json
run: |
git config user.name "bespok3d-bot"
git config user.email "bot@bespok3d.local"
git add index.json
if git diff --cached --quiet; then
echo "index unchanged; nothing to commit"
else
git commit -m "assemble sub-list index.json"
git push
fi

- name: Register this sub-list in Bespok3d/main-index (idempotent)
env:
# Fine-grained PAT with contents:write on Bespok3d/main-index (the per-repo GITHUB_TOKEN
# cannot write a sibling repo). Create it in the org and add it as this repo's secret.
MAIN_INDEX_TOKEN: ${{ secrets.MAIN_INDEX_TOKEN }}
run: |
repo_name="${GITHUB_REPOSITORY##*/}"
# github: ref (not a raw.githubusercontent URL): the app fetches sub-lists via the
# authenticated GitHub API, which works for private repos and public alike. Raw URLs
# 404 on private repos (they need an ephemeral per-user token the app cannot store).
list_url="github:${GITHUB_REPOSITORY}/index.json"
git clone "https://x-access-token:${MAIN_INDEX_TOKEN}@github.com/Bespok3d/main-index.git" main-index
mkdir -p main-index/lists
printf '{\n "name": "Reference Python Plugins",\n "url": "%s"\n}\n' "$list_url" \
> "main-index/lists/${repo_name}.json"
cd main-index
git config user.name "bespok3d-bot"
git config user.email "bot@bespok3d.local"
git add "lists/${repo_name}.json"
if git diff --cached --quiet; then
echo "list reference unchanged; nothing to commit"
else
git commit -m "register ${repo_name} sub-list"
for attempt in 1 2 3 4 5; do
git push && { echo "pushed main-index (attempt ${attempt})"; break; }
[ "$attempt" = 5 ] && { echo "main-index push failed after ${attempt} attempts"; exit 1; }
echo "main-index push rejected; rebasing on remote main (attempt ${attempt})"
git pull --rebase --no-edit origin main
done
fi
unit: repo
bake: 'true'
atom-repo: ${{ github.repository }}
list-name: 'Reference Python Plugins'
list-publisher: 'PLACEHOLDER'
list-ref-name: 'Reference Python Plugins'
main-index-repo: Bespok3d/main-index
# Per-repo Actions secret today (GitHub Free cannot org-secret private repos); becomes ONE org
# secret every repo inherits when the repos go public. See b3-builder README (secrets model).
main-index-token: ${{ secrets.MAIN_INDEX_TOKEN }}
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,31 @@ Both examples use a pure-Python dependency (`humanize`), so any interpreter work
is needed. A plugin with a compiled dependency would prebuild that wheel on an arm64 runner first (see
`u1-hw-camera`).

## Build
## Build locally

CI (`.github/workflows/release.yml`) runs `scripts/bake-deps.sh` (bakes each plugin's deps by which
requirements file it ships), then `scripts/pack.sh` (one `.b3` per `<plugin-id>/`), releases each,
assembles this repo's `index.json` sub-list, and registers it in `Bespok3d/main-index`. The baked
deps are CI artifacts and are gitignored; only the source is committed.
Needs Node.js 20+. Builds run through the shared `Bespok3d/b3-builder` tool:

```sh
npm install github:Bespok3d/b3-builder
npx b3-builder build --source ./status-feed --atom-repo Bespok3d/reference-python-plugins
# -> dist/status-feed-<ver>.b3 + dist/status-feed.atom.json
```

Drop `--source` to build every plugin in the repo at once.

The Action runs with `bake: 'true'`: a plugin that ships a `requirements.txt` or
`klipper_requirements.txt` at its root gets its Python deps downloaded for the printer platform
(aarch64, CPython 3.11) at build time. Pass `--bake` to do the same locally.

## Releasing

Bump a plugin's `manifest.json` `version` and push to `main`. CI runs the `Bespok3d/b3-builder`
Action over the whole repo, which packs each `.b3`, cuts a release per plugin, assembles this repo's
`index.json` sub-list as `Reference Python Plugins`, and registers it in `Bespok3d/main-index`
(`lists/<repo>.json`). Secret: `MAIN_INDEX_TOKEN` (contents:write on main-index). Signing deferred.

> Not yet verified on a physical U1.

## Maintainership

These plugins are published and maintained by the Bespok3d org, and several of them repackage or
Expand Down
6 changes: 4 additions & 2 deletions print-time-human/doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ to Klipper over its API.
## Build

```sh
sh scripts/fetch-deps.sh # pip install --target the deps into files/site-packages
sh scripts/pack.sh # -> dist/print-time-human-<version>.b3
npm install github:Bespok3d/b3-builder
npx b3-builder build --source ./print-time-human --atom-repo Bespok3d/reference-python-plugins --bake
# --bake installs klipper_requirements.txt into files/site-packages, then packs
# -> dist/print-time-human-<version>.b3
```
72 changes: 0 additions & 72 deletions scripts/assemble-list.mjs

This file was deleted.

61 changes: 0 additions & 61 deletions scripts/bake-deps.sh

This file was deleted.

Loading
Loading