diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index e1a72f7c..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Release -on: - release: - types: [published] - workflow_dispatch: -permissions: - contents: write -jobs: - build-and-release: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v5 - - name: Set up Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: 1.3.13 - - name: Install dependencies - run: bun install --frozen-lockfile - - name: Render bitmaps - run: bun run generate - - name: Package bitmaps (zip each subfolder) - run: | - set -euxo pipefail - shopt -s nullglob - mkdir dist - for dir in bitmaps/*; do - name="$(basename "$dir")" - (cd bitmaps && zip -r "../dist/${name}.zip" "$name") - done - - name: Upload assets to Release - uses: softprops/action-gh-release@v2 - with: - files: dist/*.zip diff --git a/.tangled/workflows/release.yml b/.tangled/workflows/release.yml new file mode 100644 index 00000000..c16354f2 --- /dev/null +++ b/.tangled/workflows/release.yml @@ -0,0 +1,93 @@ +when: + - event: ["push"] + tag: ["*"] + - event: ["manual"] + +engine: "nixery" + +dependencies: + nixpkgs/nixpkgs-unstable: + - bun + - coreutils + - curl + - git + - jq + - ouch + - xxd + +environment: + ATP_IDENTIFIER: "adam0.dev" + +steps: + - name: "Install dependencies" + command: bun install --frozen-lockfile + + - name: "Render bitmaps" + command: bun run generate + + - name: "Package bitmaps" + command: | + set -euo pipefail + shopt -s nullglob + mkdir -p dist + for dir in bitmaps/*; do + name="$(basename "$dir")" + (cd bitmaps && ouch compress "$name" "../dist/${name}.zip") + done + + - name: "Publish release artifacts" + command: | + set -euo pipefail + + if [[ "$TANGLED_PIPELINE_KIND" == "manual" ]]; then + echo "Manual pipelines build and package artifacts without publishing them." + exit 0 + fi + + resolved_did="$(curl -fsSG \ + "https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle" \ + --data-urlencode "handle=$ATP_IDENTIFIER" | jq -er .did)" + case "$resolved_did" in + did:plc:*) + pds="$(curl -fsS "https://plc.directory/$resolved_did" | jq -er \ + '[.service[] | select(.type == "AtprotoPersonalDataServer")][0].serviceEndpoint')" + ;; + *) + echo "Unsupported DID method: $resolved_did" >&2 + exit 1 + ;; + esac + pds="${pds%/}" + + session="$(curl -fsS -X POST "$pds/xrpc/com.atproto.server.createSession" \ + -H "Content-Type: application/json" \ + -d "$(jq -n \ + --arg identifier "$ATP_IDENTIFIER" \ + --arg password "$ATP_APP_PASSWORD" \ + '{identifier: $identifier, password: $password}')")" + jwt="$(jq -r .accessJwt <<<"$session")" + did="$(jq -r .did <<<"$session")" + [[ "$did" == "$resolved_did" ]] + + tag_hash="$(git rev-parse "$TANGLED_REF_NAME^{tag}")" + tag_bytes="$(printf '%s' "$tag_hash" | xxd -r -p | base64 | tr -d '=')" + + for artifact_path in dist/*.zip; do + artifact_name="$(basename "$artifact_path")" + blob="$(curl -fsS -X POST "$pds/xrpc/com.atproto.repo.uploadBlob" \ + -H "Authorization: Bearer $jwt" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@$artifact_path")" + record="$(jq -n \ + --arg did "$did" \ + --arg tag "$tag_bytes" \ + --arg name "$artifact_name" \ + --arg repo "$TANGLED_REPO_URL" \ + --arg created "$(date -Iseconds)" \ + --argjson blob "$(jq .blob <<<"$blob")" \ + '{repo: $did, collection: "sh.tangled.repo.artifact", validate: false, record: {"$type": "sh.tangled.repo.artifact", tag: {"$bytes": $tag}, name: $name, repo: $repo, artifact: $blob, createdAt: $created}}')" + curl -fsS -X POST "$pds/xrpc/com.atproto.repo.createRecord" \ + -H "Authorization: Bearer $jwt" \ + -H "Content-Type: application/json" \ + -d "$record" + done