~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0

ci: run the workflows on knotless

Merged chadtmiller.com asked to merge into main from chadtmiller.com/pds.js:ci/knotless-workflows
.knotless/workflows/canary-worker.ymlnew+32−0
@@ -0,0 +1,32 @@
# Publishes a worker artifact to the canary channel on every push to main.
# Its version is the released one plus `-canary.<commit>`. The publish
# refuses to move the channel to a commit behind the one it has, so a
# revert needs a publish by hand from a machine with the credentials.
on:
push: {refs: [refs/heads/main]}
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
secrets: [PDSJS_SITE_TOKEN]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PDS_URL: https://pds.pdsjs.dev
PDS_IDENTIFIER: pdsjs.dev
steps:
- name: check credentials
run: |
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so this push would publish nothing."
echo "Grant it in the runner's secrets file. It is an app password for $PDS_IDENTIFIER."
exit 1
fi
echo "publishing to $PDS_URL as $PDS_IDENTIFIER"
- name: build
run: |
corepack enable
pnpm install --frozen-lockfile
npm run build:ui
VERSION_SUFFIX="-canary.$(echo "$KNOTLESS_RUN_SHA" | cut -c1-7)" npm run build:worker
test -s dist/worker/index.js
test -s dist/worker/manifest.json
- name: publish
run: PDS_PASSWORD="$PDSJS_SITE_TOKEN" CHANNEL=canary node scripts/publish-worker-artifact.mjs
.knotless/workflows/ci.ymlnew+23−0
@@ -0,0 +1,23 @@
# The gate: `npm run ci`, on every branch pushed and on pulls into main.
# The UI build in it comes first: @pdsjs/account-ui exports a gitignored
# bundle, and without it tsc and the tests cannot resolve the node and
# cloudflare entrypoints. The e2e suite needs the docker-compose stack, so
# it is not part of the gate.
#
# trixie, not bookworm: better-sqlite3's prebuilt binary needs glibc 2.38
# or newer. corepack activates the pnpm that package.json pins.
on:
push: {refs: [refs/heads/*]}
pull: {base: [refs/heads/main]}
queue: first
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
steps:
- name: install
run: |
corepack enable
pnpm install --frozen-lockfile
- name: ci
run: npm run ci
.knotless/workflows/mirror-repo.ymlnew+45−0
@@ -0,0 +1,45 @@
# Mirrors main and each version tag to atproto://pdsjs.dev/pds.js, the
# dev.pdsjs.git.repo record that packages/git describes. Stock git reads it
# at https://pds.pdsjs.dev/git/pdsjs.dev/pds.js. One run pushes one ref, the
# one it runs on, so a tag push mirrors that tag alone. Nothing pushes the
# other way, and the mirror only fast-forwards to the commit run here.
#
# The push uses this repository's own helper, so the code being mirrored
# writes the mirror. PDSJS_SITE_TOKEN is an app password for pdsjs.dev,
# granted in the runner's secrets file to main and v* tags.
on:
push: {refs: [refs/heads/main, refs/tags/v*]}
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
secrets: [PDSJS_SITE_TOKEN]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PDS_IDENTIFIER: pdsjs.dev
MIRROR_REMOTE: atproto://pdsjs.dev/pds.js
steps:
- name: check credentials
run: |
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so this push would mirror nothing."
echo "Grant it in the runner's secrets file. It is an app password for $PDS_IDENTIFIER."
exit 1
fi
- name: install the helper
run: |
corepack enable
pnpm --filter @pdsjs/git install --frozen-lockfile
ln -sf "$PWD/packages/git/src/cli.js" /usr/local/bin/git-remote-atproto
# A push that loses the record's compare-and-swap to another is told to
# fetch and retry. Each attempt reads the record again.
- name: push
run: |
git config --global --add safe.directory "$PWD"
refspec="$KNOTLESS_RUN_SHA:$KNOTLESS_RUN_REF"
for attempt in 1 2 3; do
echo "push $refspec to $MIRROR_REMOTE (attempt $attempt)"
if ATPROTO_GIT_PASSWORD="$PDSJS_SITE_TOKEN" git push "$MIRROR_REMOTE" "$refspec"; then
exit 0
fi
sleep 5
done
exit 1
.knotless/workflows/publish-git-app.ymlnew+29−0
@@ -0,0 +1,29 @@
# Publishes the repository browser to git.pdsjs.dev on every push to main,
# and repins the manifest that an install tracks. The deploy writes a
# record only when the build changes it, so a push that leaves the browser
# alone moves no CID.
on:
push: {refs: [refs/heads/main]}
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
secrets: [PDSJS_SITE_TOKEN]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PDS_URL: https://pds.pdsjs.dev
PDS_DID: did:plc:ye5hhvya5o2fwvouv3wttkkn
steps:
- name: check credentials
run: |
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so this push would publish nothing."
echo "Grant it in the runner's secrets file. It is an app password for pdsjs.dev."
exit 1
fi
echo "publishing to $PDS_URL as $PDS_DID"
- name: build
run: |
corepack enable
pnpm install --frozen-lockfile
pnpm --filter @pdsjs/git-ui run build
- name: publish
run: PDS_APP_PASSWORD="$PDSJS_SITE_TOKEN" node packages/git-ui/scripts/deploy.mjs
.knotless/workflows/publish-spaces-app.ymlnew+33−0
@@ -0,0 +1,33 @@
# Publishes the space browser to spaces.pdsjs.dev on every push to main.
# The deploy writes a record only when the build changes it.
on:
push: {refs: [refs/heads/main]}
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
secrets: [PDSJS_SITE_TOKEN]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PDS_URL: https://pds.pdsjs.dev
PDS_DID: did:plc:ye5hhvya5o2fwvouv3wttkkn
# The site record's key is the subdomain it answers on, and the origin is
# where that subdomain answers. The two must agree: the origin goes into
# the OAuth client document, and an authorization server refuses a
# document that names anywhere other than where it was fetched from.
SPACES_SITE: spaces
SPACES_ORIGIN: https://spaces.pdsjs.dev
steps:
- name: check credentials
run: |
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so this push would publish nothing."
echo "Grant it in the runner's secrets file. It is an app password for pdsjs.dev."
exit 1
fi
echo "publishing to $PDS_URL as $PDS_DID, signing in as $SPACES_ORIGIN/client-metadata.json"
- name: build
run: |
corepack enable
pnpm install --frozen-lockfile
pnpm --filter @pdsjs/spaces-ui run build
- name: publish
run: PDS_APP_PASSWORD="$PDSJS_SITE_TOKEN" node packages/spaces-ui/scripts/deploy.mjs
.knotless/workflows/publish-wizard.ymlnew+29−0
@@ -0,0 +1,29 @@
# Publishes the setup wizard to start.pdsjs.dev on every push to main.
on:
push: {refs: [refs/heads/main]}
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
secrets: [PDSJS_SITE_TOKEN]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PDS_URL: https://pds.pdsjs.dev
PDS_IDENTIFIER: pdsjs.dev
# Public either way: the site serves them in config.json.
OAUTH_CLIENT_ID: 54445ecf5107dc657b05f88b9ab1f12d
OAUTH_SCOPES: account-settings.read workers-scripts.write workers-r2.write zone.read dns.write
steps:
- name: check credentials
run: |
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so this push would publish nothing."
echo "Grant it in the runner's secrets file. It is an app password for $PDS_IDENTIFIER."
exit 1
fi
echo "publishing to $PDS_URL as $PDS_IDENTIFIER"
- name: build
run: |
corepack enable
pnpm install --frozen-lockfile
pnpm --filter @pdsjs/start run build
- name: publish
run: PDS_PASSWORD="$PDSJS_SITE_TOKEN" pnpm --filter @pdsjs/start run publish-site
.knotless/workflows/README.mdnew+35−0
@@ -0,0 +1,35 @@
# Workflows
knotless.dev's hosted runner runs these for chadtmiller.com/pds.js. The
format is in knotless's
[workflow reference](https://knotless.dev/chadtmiller.com/knotless/blob/main/docs/reference/workflows.md).
The runner reads only the `.yml`, `.yaml` and `.json` files here. Each
workflow says what it does, and why, in its comments.
- `ci` is the gate, on every branch and on pulls into main.
- `mirror-repo` pushes main and each `v*` tag to `atproto://pdsjs.dev/pds.js`.
- `canary-worker`, `publish-git-app`, `publish-spaces-app` and
`publish-wizard` publish on every push to main.
- `release-npm`, `release-worker`, `release-image` and
`release-runner-image` publish on a `v*` tag, which `npm run release:cut`
pushes.
Each step runs in a container with no docker daemon, so the two image
workflows build with kaniko.
## Secrets
A pull gets no secrets. The runner grants these from its secrets file,
under `did:plc:bcgltzqazw5tb6k2g3ttenbj/pds.js`, to the refs named:
- `PDSJS_SITE_TOKEN`, an app password for pdsjs.dev, to main and `v*` tags.
The mirror, the sites, the worker artifacts and the PDS registry copies
use it.
- `NPM_TOKEN`, an npm automation token with publish rights for the
`@pdsjs` scope, to `v*` tags.
- `RELEASE_PASSWORD`, an app password for chadtmiller.com, to `v*` tags.
The image workflows publish the images with it, as the repository's
owner.
A workflow that is not granted a secret it needs fails at its first step
and says which one.
.knotless/workflows/release-image.ymlnew+122−0
@@ -0,0 +1,122 @@
# Builds the PDS container image on a version tag, and publishes it as the
# `pds.js` release of this repository, which knotless.dev serves as
# `docker pull knotless.dev/chadtmiller.com/pds.js/pds.js:<version>`. It
# copies it to the pdsjs.dev PDS's own registry (@pdsjs/oci) too.
#
# The runner gives a step no docker daemon, so kaniko builds the image. Once
# a build ends, kaniko leaves the image's filesystem at /, and
# scripts/run-image.mjs runs the smoke test in it as the image would run.
# The image goes up as the OCI layout kaniko writes, with `knotless publish
# --oci`, as the repository's owner: RELEASE_PASSWORD is an app password of
# theirs, granted to v* tags in the runner's secrets file.
#
# Asked for at a branch, `knotless rerun knotless://chadtmiller.com/pds.js
# --ref refs/heads/<branch> --workflow release-image`, it builds and tests
# the image and publishes nothing.
on:
push: {refs: [refs/tags/v*]}
asked: {refs: [refs/heads/*]}
superseded: finish
image: buildpack-deps:trixie-curl
secrets: [RELEASE_PASSWORD, PDSJS_SITE_TOKEN]
env:
REPO: knotless://chadtmiller.com/pds.js
PACKAGE: pds.js
DOCKERFILE: Dockerfile
KNOTLESS_APPVIEW: https://knotless.dev
PDS_HOST: pds.pdsjs.dev
CRANE_VERSION: v0.20.2
KANIKO_IMAGE: gcr.io/kaniko-project/executor:v1.23.2
# Where kaniko's own image keeps them. A build replaces the rest of /.
SSL_CERT_DIR: /kaniko/ssl/certs
DOCKER_CONFIG: /kaniko/.docker
steps:
- name: check credentials
run: |
case "$KNOTLESS_RUN_REF" in
refs/tags/v*)
if [ -z "${RELEASE_PASSWORD:-}" ]; then
echo "RELEASE_PASSWORD is not granted, so this tag would publish nothing."
echo "Grant it in the runner's secrets file. It is an app password for the repository's owner."
exit 1
fi ;;
*) echo "at $KNOTLESS_RUN_REF: building and testing, publishing nothing" ;;
esac
# kaniko's own image starts kaniko, not the command the runner keeps a
# container up with, so the steps take kaniko from its image. They run in
# Debian, whose /sbin is a link as in the images built: the runner mounts
# docker-init under /sbin, and a build cannot replace a directory that
# holds a mount with a link. The tools go under /kaniko, which a build
# leaves alone.
- name: tools
run: |
mkdir -p /kaniko/tools
cd /kaniko/tools
curl -fsSL "https://github.com/google/go-containerregistry/releases/download/$CRANE_VERSION/go-containerregistry_Linux_x86_64.tar.gz" | tar -xzf - crane
./crane export "$KANIKO_IMAGE" - | tar -xf - -C / kaniko
/kaniko/executor version
v=$(curl -fsSL https://knotless.dev/releases/latest)
name="knotless-$v-x86_64-unknown-linux-musl"
curl -fsSLO "https://knotless.dev/releases/$v/$name.tar.gz"
curl -fsSL -o sum "https://knotless.dev/releases/$v/$name.tar.gz.sha256"
[ "$(sha256sum "$name.tar.gz" | cut -d' ' -f1)" = "$(cut -d' ' -f1 sum)" ]
tar -xzf "$name.tar.gz"
mv "$name/knotless" knotless
- name: build
timeout: 45
run: |
# kaniko builds over the files of the image the steps run in, and
# removes them only between stages. A first stage of nothing makes it
# remove them before the Dockerfile's own stages.
{ echo 'FROM scratch AS empty'; cat "$DOCKERFILE"; } > /kaniko/Dockerfile
/kaniko/executor --force --context "dir://$PWD" --dockerfile /kaniko/Dockerfile \
--no-push --oci-layout-path /kaniko/image --snapshot-mode redo
cat /kaniko/image/index.json
# A tagged image that cannot boot is worse than no image. Every variable
# the entrypoint demands is set here: a new one in docker/server.js fails
# this test until it is added here too.
- name: smoke test
run: |
node scripts/run-image.mjs /kaniko/image \
PDS_HOSTNAME=pds.example.com JWT_SECRET=smoke-test-secret \
PDS_PASSWORD=smoke-test-password PDS_ENABLE_SPACES=true > /tmp/server.log 2>&1 &
server=$!
health='fetch("http://127.0.0.1:3000/xrpc/_health").then(r=>process.exit(r.ok?0:1),()=>process.exit(1))'
for _ in $(seq 1 30); do
if node -e "$health"; then
kill "$server"
echo "the image answers its health check"
exit 0
fi
kill -0 "$server" 2>/dev/null || break
sleep 1
done
tail -30 /tmp/server.log
kill "$server" 2>/dev/null || true
exit 1
- name: publish
run: |
case "$KNOTLESS_RUN_REF" in refs/tags/v*) ;; *) exit 0 ;; esac
version="${KNOTLESS_RUN_REF#refs/tags/v}"
KNOTLESS_PASSWORD="$RELEASE_PASSWORD" /kaniko/tools/knotless publish "$REPO" "$PACKAGE" "$version" --oci /kaniko/image
# A copy, like a mirror: it never fails a release on its own. A PDS
# without the feature answers /v2/ with 404 rather than the challenge.
- name: copy to the PDS
run: |
case "$KNOTLESS_RUN_REF" in refs/tags/v*) ;; *) exit 0 ;; esac
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so the PDS copy is skipped"
exit 0
fi
status=$(node -e "fetch('https://$PDS_HOST/v2/').then((r) => console.log(r.status)).catch(() => console.log(0))")
if [ "$status" != "401" ]; then
echo "https://$PDS_HOST/v2/ answered $status, not the challenge, so the PDS registry is off"
exit 0
fi
tag="${KNOTLESS_RUN_REF#refs/tags/}"
crane=/kaniko/tools/crane
echo "$PDSJS_SITE_TOKEN" | $crane auth login "$PDS_HOST" -u pdsjs.dev --password-stdin
if ! $crane push /kaniko/image "$PDS_HOST/$PACKAGE:$tag" || ! $crane tag "$PDS_HOST/$PACKAGE:$tag" latest; then
echo "the PDS refused the push. A layer can be over the platform's request limit"
echo "(100 MB on the lowest Cloudflare plan). The release stands on knotless."
fi
.pdsjs/workflows/release-npm.yml → .knotless/workflows/release-npm.ymlrenamed+26−44
@@ -1,96 +1,78 @@
# Publishes the packages to npm on a version tag. The tag reaches the
# repository record because mirror-repo.yml mirrors it, one tag per run.
name: release-npm
refs: [refs/tags/v*]
# Visible to anyone reading the repo, so only non-secret values belong here.
env:
PDS_HOST: "pds.pdsjs.dev"
# Publishes the packages to npm on a version tag, and copies them to the
# pdsjs.dev PDS's own npm registry (@pdsjs/npm). changeset publish takes
# every package whose version is not on npm, so a package releases for the
# first time with no changeset at all.
on:
push: {refs: [refs/tags/v*]}
superseded: finish
image: node:22-trixie
cache: [/root/.local/share/pnpm/store, /root/.cache/node/corepack]
secrets: [NPM_TOKEN, PDSJS_SITE_TOKEN]
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PDS_HOST: pds.pdsjs.dev
steps:
- name: check publish credentials
- name: check credentials
run: |
set -e
if [ -z "${NPM_TOKEN:-}" ]; then
echo "NPM_TOKEN is not granted, so this tag would publish nothing."
echo "Grant it in the runner's secrets file. It is an npm automation token with publish rights for the @pdsjs scope."
exit 1
fi
# A tag that does not name the versioned state would mislabel every
# package, and changeset publish cannot be taken back.
- name: check the tag names the versioned state
run: |
set -e
tag="${PDSJS_CI_REF#refs/tags/}"
tag="${KNOTLESS_RUN_REF#refs/tags/}"
core=$(node -p 'require("./packages/core/package.json").version')
if [ "v$core" != "$tag" ]; then
echo "tag is $tag but @pdsjs/core is $core"
echo "the tag is $tag but @pdsjs/core is $core"
exit 1
fi
pending=$(ls .changeset/*.md 2>/dev/null | grep -cv README || true)
if [ "$pending" != "0" ]; then
echo "$pending changeset(s) still pending. Run version-packages first."
echo "$pending changesets are pending. Run version-packages first."
exit 1
fi
# changeset publish takes every package whose version is not on npm, which
# is how a package releases for the first time with no changeset at all.
- name: build and publish to npm
- name: publish to npm
run: |
set -e
echo "==> pnpm install"
corepack enable
pnpm install --frozen-lockfile
echo '==> build (generates the .d.ts files publish ships)'
pnpm run build
{
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}"
echo "git-checks=false"
} > .npmrc
echo "==> changeset publish"
pnpm exec changeset publish --no-git-tag
# The pdsjs.dev PDS is itself an npm registry (the @pdsjs/npm package), so
# the release also lands in the account that owns the @pdsjs scope. The
# site token, an app password for pdsjs.dev, signs in. Every public
# package at its current version goes up, skipping versions the PDS
# already holds, so a run after a gap backfills and ordinary runs carry
# only the new versions. A copy like the ghcr mirror: it never fails a
# release on its own.
- name: publish to the account's PDS
# Every public package goes up at its current version, less the versions
# the PDS holds, so a run after a gap fills it in. Like a mirror, it never
# fails a release on its own.
- name: publish to the PDS
run: |
set -e
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so the PDS copy is skipped"
exit 0
fi
registry="https://$PDS_HOST/npm/"
status=$(node -e "fetch('$registry-/ping').then((r) => console.log(r.status)).catch(() => console.log(0))")
if [ "$status" != "200" ]; then
echo "$registry answered $status to the ping; the PDS registry is off"
echo "and this step skips"
echo "$registry answered $status to the ping, so the PDS registry is off and this step skips"
exit 0
fi
echo "//$PDS_HOST/npm/:_authToken=${PDSJS_SITE_TOKEN}" >> .npmrc
for dir in packages/*/; do
name=$(node -p "require('./$dir/package.json').name" 2>/dev/null) || continue
private=$(node -p "Boolean(require('./$dir/package.json').private)")
version=$(node -p "require('./$dir/package.json').version")
[ "$private" = "true" ] && continue
if npm view "$name@$version" version --registry "$registry" >/dev/null 2>&1; then
echo "$name@$version is already on the PDS"
echo "$name@$version is on the PDS already"
continue
fi
# pnpm rewrites workspace:* ranges at pack time, the way the npmjs
# publish path does through changesets.
# pnpm rewrites workspace:* ranges as it packs, as changesets does.
if (cd "$dir" && pnpm publish --registry "$registry" --no-git-checks --access public); then
echo "published $name@$version to the PDS"
else
echo "the PDS refused $name@$version; the release already stands on npmjs"
echo "the PDS refused $name@$version; the release stands on npmjs"
fi
done
.knotless/workflows/release-runner-image.ymlnew+132−0
@@ -0,0 +1,132 @@
# Builds the image of @pdsjs/git-ci, the check runner, on a version tag,
# and publishes it as the `pds.js-git-ci` release of this repository:
# `docker pull knotless.dev/chadtmiller.com/pds.js/pds.js-git-ci:<version>`.
# It copies it to the pdsjs.dev PDS's own registry too. release-image.yml
# says how the image is built and published with no docker daemon.
on:
push: {refs: [refs/tags/v*]}
asked: {refs: [refs/heads/*]}
superseded: finish
image: buildpack-deps:trixie-curl
secrets: [RELEASE_PASSWORD, PDSJS_SITE_TOKEN]
env:
REPO: knotless://chadtmiller.com/pds.js
PACKAGE: pds.js-git-ci
DOCKERFILE: packages/git-ci/Dockerfile
KNOTLESS_APPVIEW: https://knotless.dev
PDS_HOST: pds.pdsjs.dev
CRANE_VERSION: v0.20.2
KANIKO_IMAGE: gcr.io/kaniko-project/executor:v1.23.2
# Where kaniko's own image keeps them. A build replaces the rest of /.
SSL_CERT_DIR: /kaniko/ssl/certs
DOCKER_CONFIG: /kaniko/.docker
steps:
- name: check credentials
run: |
case "$KNOTLESS_RUN_REF" in
refs/tags/v*)
if [ -z "${RELEASE_PASSWORD:-}" ]; then
echo "RELEASE_PASSWORD is not granted, so this tag would publish nothing."
echo "Grant it in the runner's secrets file. It is an app password for the repository's owner."
exit 1
fi ;;
*) echo "at $KNOTLESS_RUN_REF: building and testing, publishing nothing" ;;
esac
# kaniko's own image starts kaniko, not the command the runner keeps a
# container up with, so the steps take kaniko from its image. They run in
# Debian, whose /sbin is a link as in the images built: the runner mounts
# docker-init under /sbin, and a build cannot replace a directory that
# holds a mount with a link. The tools go under /kaniko, which a build
# leaves alone.
- name: tools
run: |
mkdir -p /kaniko/tools
cd /kaniko/tools
curl -fsSL "https://github.com/google/go-containerregistry/releases/download/$CRANE_VERSION/go-containerregistry_Linux_x86_64.tar.gz" | tar -xzf - crane
./crane export "$KANIKO_IMAGE" - | tar -xf - -C / kaniko
/kaniko/executor version
v=$(curl -fsSL https://knotless.dev/releases/latest)
name="knotless-$v-x86_64-unknown-linux-musl"
curl -fsSLO "https://knotless.dev/releases/$v/$name.tar.gz"
curl -fsSL -o sum "https://knotless.dev/releases/$v/$name.tar.gz.sha256"
[ "$(sha256sum "$name.tar.gz" | cut -d' ' -f1)" = "$(cut -d' ' -f1 sum)" ]
tar -xzf "$name.tar.gz"
mv "$name/knotless" knotless
- name: build
timeout: 45
run: |
# kaniko builds over the files of the image the steps run in, and
# removes them only between stages. A first stage of nothing makes it
# remove them before the Dockerfile's own stages.
{ echo 'FROM scratch AS empty'; cat "$DOCKERFILE"; } > /kaniko/Dockerfile
/kaniko/executor --force --context "dir://$PWD" --dockerfile /kaniko/Dockerfile \
--no-push --oci-layout-path /kaniko/image --snapshot-mode redo
cat /kaniko/image/index.json
# The daemon listens on no port and exits without credentials, so the
# test is what it prints, and as which user.
- name: smoke test
run: |
run="node scripts/run-image.mjs /kaniko/image"
# Named no repositories, the CLI prints its usage and exits 129.
code=0
usage=$($run 2>&1) || code=$?
if [ "$code" != 129 ]; then
echo "expected exit 129 with no repositories, got $code"
echo "$usage"
exit 1
fi
case "$usage" in
*PDSJS_CI_IDENTIFIER*) ;;
*) echo "the usage text is missing: $usage"; exit 1 ;;
esac
# Given a repository and no credentials, it reaches the credential check.
fatal=$($run PDSJS_CI_REPOS=alice.example.com/repo 2>&1) || true
case "$fatal" in
*"must both be set"*) ;;
*) echo "expected the credential error, got: $fatal"; exit 1 ;;
esac
# The entrypoint takes the state directory as root, then drops.
who=$($run -- id -un)
if [ "$who" != node ]; then
echo "steps would run as $who, not node"
exit 1
fi
# A workflow clones the repository under test, installs it, and may
# build an image. Without any one of these a run fails at its first step.
$run -- sh -c '
set -e
git --version
corepack --version
command -v git-remote-atproto
command -v g++
docker --version
docker buildx version
'
- name: publish
run: |
case "$KNOTLESS_RUN_REF" in refs/tags/v*) ;; *) exit 0 ;; esac
version="${KNOTLESS_RUN_REF#refs/tags/v}"
KNOTLESS_PASSWORD="$RELEASE_PASSWORD" /kaniko/tools/knotless publish "$REPO" "$PACKAGE" "$version" --oci /kaniko/image
- name: copy to the PDS
run: |
case "$KNOTLESS_RUN_REF" in refs/tags/v*) ;; *) exit 0 ;; esac
if [ -z "${PDSJS_SITE_TOKEN:-}" ]; then
echo "PDSJS_SITE_TOKEN is not granted, so the PDS copy is skipped"
exit 0
fi
status=$(node -e "fetch('https://$PDS_HOST/v2/').then((r) => console.log(r.status)).catch(() => console.log(0))")
if [ "$status" != "401" ]; then
echo "https://$PDS_HOST/v2/ answered $status, not the challenge, so the PDS registry is off"
exit 0
fi
tag="${KNOTLESS_RUN_REF#refs/tags/}"
crane=/kaniko/tools/crane
echo "$PDSJS_SITE_TOKEN" | $crane auth login "$PDS_HOST" -u pdsjs.dev --password-stdin
if ! $crane push /kaniko/image "$PDS_HOST/$PACKAGE:$tag" || ! $crane tag "$PDS_HOST/$PACKAGE:$tag" latest; then
echo "the PDS refused the push. A layer can be over the platform's request limit"
echo "(100 MB on the lowest Cloudflare plan). The release stands on knotless."
fi
.knotless/workflows/release-worker.ymlnew+41−0
.pdsjs/workflows/canary-worker.ymldeleted+0−46
.pdsjs/workflows/ci.ymldeleted+0−17
.pdsjs/workflows/publish-git-app.ymldeleted+0−37
.pdsjs/workflows/publish-spaces-app.ymldeleted+0−43
.pdsjs/workflows/publish-wizard.ymldeleted+0−35
.pdsjs/workflows/README.mddeleted+0−50
.pdsjs/workflows/release-image.ymldeleted+0−152
.pdsjs/workflows/release-runner-image.ymldeleted+0−162
.pdsjs/workflows/release-worker.ymldeleted+0−52
.tangled/workflows/ci.ymldeleted+0−62
.tangled/workflows/mirror-repo.ymldeleted+0−141
packages/core/test/commit-diff.test.js+7−7
packages/start/README.md+1−1
scripts/cut-release.mjs+3−4
scripts/run-image.mjsnew+70−0