Elyra
Elyra The coding agent eTerm The terminal that knows where each command ends Huskarl AI colleagues on your own Mac Starf An activity monitor for Apple silicon that never invents a number etrans An SSH and SFTP client for macOS Elyra VM Virtual machines for macOS, Linux and Windows on your Mac Litr A small, native web browser for macOS Notr A notebook for macOS e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Refr Local-first PDF workspace for macOS Elyra Workspace A desktop workspace for coding agents eDock A container runtime for the Mac Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Release notes
Release notes
Elyra

Releasing

A release is a signed, notarized eDock-<version>-arm64.dmg on GitHub. scripts/bundle.sh makes it.

Once per Mac

  1. A Developer ID Application certificate in your keychain. Check it with:

    security find-identity -v -p codesigning
    
  2. Notarization credentials in the keychain, under a profile name. Use an app-specific password from appleid.apple.com. Type it at the prompt, never on the command line or in a chat:

    xcrun notarytool store-credentials edock-notary --apple-id <apple-id> --team-id <team-id>
    
  3. cargo-about, for the licence notices: cargo install cargo-about --locked --features cli.

  4. The engine's guest, built once: cargo xtask kernel && cargo xtask disk && cargo xtask guest in engine/.

  5. The update key in ~/.config/edock/update-key. Installed copies of eDock accept an update only when it's signed with this key. Its public half is UPDATE_KEY in desktop/src/main.rs.

    • The key already exists. Copy it into a password manager or another safe place. If it's lost, installed copies can't take updates any more until people install a new version by hand.
    • On a new Mac, copy the file there with mode 600, or point EDOCK_UPDATE_KEY at it.
    • Never commit it.
    • Only when starting over with a new key: scripts/update-key/target/release/update-key keygen. Then put the public key it prints into UPDATE_KEY. Copies already installed will only accept updates signed with the old key.

Make a release

First, with eDock quit (the app is single-instance, so codegen does nothing while it runs), regenerate the bindings and commit them if they changed: cd desktop && rata codegen. CI's Bindings match the commands fails when app/src/bindings.ts is stale.

EDOCK_SIGN_ID="Developer ID Application: <name> (<team-id>)" \
EDOCK_NOTARY_PROFILE=edock-notary \
EDOCK_RELEASE_NOTES=notes.md \
  scripts/bundle.sh --version 0.3.0 --notarize

This takes about 15 minutes, most of it waiting for Apple. It:

  1. Sets the version in desktop/elyra.toml, desktop/Cargo.toml and engine/Cargo.toml. One number then covers the app, its About box and the engine's /version. Without --version, the script refuses to build when the three differ.

  2. Builds the engine (cargo xtask host, cargo xtask bundle).

  3. Regenerates desktop/NOTICE (scripts/notices.sh, with cargo about): the licences of the app's Rust crates and of the JavaScript in its window. It goes into the app as Contents/Resources/NOTICE, with the MIT LICENSE, and the engine's NOTICE and LICENSE go in Contents/Resources/engine/.

  4. Builds the app (npm run build, rata bundle).

  5. Puts the engine into the app: Contents/MacOS/edock, plus Contents/Resources/guest, the kernel, initramfs and disk template. Kiri's licence goes in Contents/Resources/engine.

  6. Signs:

    • the engine, with the com.apple.security.virtualization entitlement;
    • then the app around it.

    Both use the hardened runtime and a secure timestamp. rata bundle signs with --deep, which would drop the engine's entitlement, so the engine is signed again on its own. The script checks the entitlement is there.

  7. Notarizes the app and staples its ticket, so the copy in Applications opens without a network.

  8. Makes the update:

    • dist/eDock-<version>-arm64.zip, the stapled app, zipped with --norsrc so it stays sealed;
    • dist/latest.json, which names that zip with its SHA-256, the update key's signature and the notes from EDOCK_RELEASE_NOTES.

    Before any of this, the script checks that the update key matches the app's UPDATE_KEY, so a mismatch stops it at once rather than after 15 minutes.

  9. Writes the kernel's source archive, dist/eDock-<version>-kernel-source.tar.xz: the exact Linux release with eDock's patches applied, and its build inputs. GPL-2.0 asks that this be published beside the binaries; KERNEL_SOURCE_OFFER.md in the app names it. It takes about 6 minutes and is about 160 MB.

  10. Makes the .dmg (the app and a link to Applications), signs it, notarizes it, and staples it.

  11. Checks both with spctl, and writes dist/eDock-<version>-arm64.dmg.sha256.

If Apple rejects either submission, the script prints Apple's log with the reason, and stops.

Publish

git add desktop engine scripts docs README.md LICENSE && git commit -m "eDock 0.3.0"
git tag -a v0.3.0 -m "eDock 0.3.0"
git push origin main v0.3.0
gh release create v0.3.0 dist/eDock-0.3.0-arm64.dmg dist/eDock-0.3.0-arm64.dmg.sha256 \
  dist/eDock-0.3.0-arm64.zip dist/latest.json dist/eDock-0.3.0-kernel-source.tar.xz \
  --title "eDock 0.3.0" --notes-file notes.md --latest

The release must be marked latest, and must carry latest.json and the zip, for installed copies to find it. latest.json names the zip at releases/download/v0.3.0/…, so the tag and the version must agree.

Then check what people will download:

gh release download v0.3.0 -D /tmp/check && cd /tmp/check
shasum -a 256 -c eDock-0.3.0-arm64.dmg.sha256
xcrun stapler validate eDock-0.3.0-arm64.dmg

And what an installed eDock will get:

cd desktop && cargo test published_release -- --ignored

This test fetches the published latest.json, downloads the zip it names, and checks the zip's signature against the app's UPDATE_KEY and its SHA-256, just as an update does before installing.

Local builds

Without --notarize the app is signed ad hoc. It runs on the Mac that built it, and Gatekeeper refuses it elsewhere.

scripts/bundle.sh                 # desktop/target/release/bundle/eDock.app
scripts/bundle.sh --dmg           # … and dist/eDock-<version>-arm64.dmg
scripts/bundle.sh --skip-engine   # reuse the engine already built

In CI

An App Store Connect API key replaces the keychain profile:

EDOCK_NOTARY_KEY=/path/AuthKey_XXXX.p8 EDOCK_NOTARY_KEY_ID=XXXX EDOCK_NOTARY_ISSUER=<issuer-uuid> \
EDOCK_SIGN_ID="Developer ID Application: …" scripts/bundle.sh --version 0.3.0 --notarize

The CI machine's keychain still needs the Developer ID certificate.

Versions

eDock uses semantic versions (MAJOR.MINOR.PATCH). An engine built from a checkout without a release version reports 0.0.0, and edock skips its engine version check for that.