-
Notifications
You must be signed in to change notification settings - Fork 0
Make the applications installable, and point them at a server #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
298d5b4
3027909
cc6fe13
72d7954
5c58578
887dd7f
cf6f79a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,22 @@ | |
| # A manifest is a claim about a build somebody can install. `dev` moves several times a day and | ||
| # nothing deploys from it; a manifest per commit would be a list of hashes nobody could act on, | ||
| # and would make the released ones harder to find. | ||
| # | ||
| # # The desktop job, and why the binaries are unsigned | ||
| # | ||
| # Windows code signing is a certificate somebody rents; Apple notarisation is a developer account | ||
| # somebody rents. Neither was bought, so the installers carry no platform signature: Windows shows | ||
| # SmartScreen, macOS asks for a right-click. That is a real cost at the door and it is written into | ||
| # `README.md` rather than left to be discovered. | ||
| # | ||
| # What replaces it is the same thing that carries the web manifest: `SHA256SUMS` per platform, | ||
| # attested through Sigstore to this commit and this workflow. It is a weaker promise about *who | ||
| # vouches* and a stronger one about *what was built* — a signature says a key-holder approved the | ||
| # bytes, an attestation says which source produced them. | ||
| # | ||
| # The repository's own Ed25519 key (`scripts/release.sh`, `release/whispee.pub`) stays what it is: | ||
| # the reproducible local build. `verify-release.sh` already states its limit — the key lives in the | ||
| # repository, so whoever controls the repository can replace it. | ||
| name: Release | ||
|
|
||
| on: | ||
|
|
@@ -113,3 +129,118 @@ jobs: | |
| the same claim." \ | ||
| release/web/WEB-SHA256SUMS \ | ||
| release/web/BUILD-INFO | ||
|
|
||
| desktop: | ||
| name: Desktop installers | ||
| # The release has to exist before anything can be added to it, and `web` is what creates it. | ||
| # On `workflow_dispatch` this job still builds — the point of a rehearsal is to find out | ||
| # whether it builds — and publishes nothing, exactly like `web`. | ||
| needs: web | ||
|
|
||
| strategy: | ||
| # One platform failing must not cancel the other two: a broken macOS build is not a reason | ||
| # to lose a Windows installer that was already compiling. | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| # **22.04 rather than `ubuntu-latest`, and it is a compatibility decision.** A binary | ||
| # linked against 24.04's glibc refuses to start on anything older, and "works on the | ||
| # newest Ubuntu only" is not what a `.deb` is for. | ||
| - os: ubuntu-22.04 | ||
| bundles: deb,rpm,appimage | ||
| artefacts: target/release/bundle/{deb/*.deb,rpm/*.rpm,appimage/*.AppImage} | ||
| - os: windows-latest | ||
| bundles: msi,nsis | ||
| artefacts: target/release/bundle/{msi/*.msi,nsis/*.exe} | ||
| # **Apple Silicon only.** `macos-14` is arm64, so this produces an arm64 `.dmg` and | ||
| # nothing for an Intel Mac. Building both would mean a second runner or a universal | ||
| # binary; neither is done here, and the gap is named in `README.md` rather than | ||
| # discovered by somebody downloading a file that will not open. | ||
| - os: macos-14 | ||
| bundles: dmg | ||
| artefacts: target/release/bundle/dmg/*.dmg | ||
|
|
||
| runs-on: ${{ matrix.os }} | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v5 | ||
|
|
||
| # Tauri links against the system webview, and without these `glib-sys`'s build script fails | ||
| # on `pkg-config` before anything is compiled. Same list as the `desktop` job in `test.yml`. | ||
| - name: Tauri's system dependencies | ||
| if: runner.os == 'Linux' | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y libwebkit2gtk-4.1-dev libgtk-3-dev libsoup-3.0-dev \ | ||
| libjavascriptcoregtk-4.1-dev librsvg2-dev patchelf | ||
|
|
||
| - name: Toolchain | ||
| run: rustup toolchain install | ||
|
|
||
| - uses: Swatinem/rust-cache@v2 | ||
|
|
||
| # The same pinning as the `web` job above, and for a related reason: the interface inside | ||
| # these binaries is the same bundle the manifest describes, so it is built the same way. | ||
| - uses: actions/setup-node@v5 | ||
| with: | ||
| node-version-file: apps/web/.nvmrc | ||
| package-manager-cache: false | ||
|
|
||
| - name: Enable pnpm | ||
| run: corepack enable && corepack prepare pnpm@11.22.0 --activate | ||
|
|
||
| - name: Install the Tauri CLI | ||
| run: cargo install tauri-cli --version "^2" --locked | ||
|
|
||
| # **The version comes from the tag, not from `tauri.conf.json`.** | ||
| # | ||
| # Two files already carry a version — the manifest and `apps/desktop/Cargo.toml` — and a | ||
| # third place to bump is a third place to forget. Taking it from the ref means an installer | ||
| # is named after the release it is attached to, by construction. On a rehearsal there is no | ||
| # tag, so the file's own value stands. | ||
| - name: Build the installers | ||
| working-directory: apps/desktop | ||
| shell: bash | ||
| run: | | ||
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | ||
| cargo tauri build --bundles ${{ matrix.bundles }} \ | ||
| --config "{\"version\": \"${GITHUB_REF_NAME#v}\"}" | ||
| else | ||
| cargo tauri build --bundles ${{ matrix.bundles }} | ||
| fi | ||
|
|
||
| # Collected into one directory so the hash file, the attestation and the upload all name the | ||
| # same paths — three globs that have to agree is three chances for one of them to quietly | ||
| # match nothing. | ||
| - name: Collect and hash | ||
| shell: bash | ||
| run: | | ||
| shopt -s globstar nullglob | ||
| mkdir -p release/desktop | ||
| cp ${{ matrix.artefacts }} release/desktop/ | ||
| cd release/desktop | ||
| # Refuse an empty directory loudly. A release carrying a `SHA256SUMS` with no files | ||
| # beside it is worse than a failed job: it looks like a successful publication. | ||
| [ -n "$(ls -A)" ] || { echo "no bundle was produced" >&2; exit 1; } | ||
| sha256sum * > SHA256SUMS | ||
| cat SHA256SUMS | ||
|
|
||
| # The bundles themselves, not the hash file. On the web side the manifest *is* the artefact, | ||
| # because the bytes being checked live on somebody else's server; here the bytes are what is | ||
| # downloaded, so that is what the provenance has to bind. | ||
| - uses: actions/attest-build-provenance@v3 | ||
| with: | ||
| # The hash file is excluded rather than attested alongside: it describes the bundles, and | ||
| # a provenance statement about a list of hashes is one indirection away from the thing | ||
| # somebody actually runs. | ||
| subject-path: | | ||
| release/desktop/* | ||
| !release/desktop/SHA256SUMS | ||
|
|
||
| - name: Publish | ||
| if: startsWith(github.ref, 'refs/tags/') | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| gh release upload "${GITHUB_REF_NAME}" release/desktop/* --clobber | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
All three matrix jobs create an asset named Useful? React with 👍 / 👎. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -124,6 +124,28 @@ pub fn session_clear(vault: State<'_, Vault>) -> Result<(), String> { | |
| } | ||
| } | ||
|
|
||
| /// The delivery service this installation was pointed at, or `None` before it has been. | ||
| /// | ||
| /// `None` is what puts `apps/web/src/app/ServerSetup.tsx` on screen instead of the application. | ||
| /// It is a first-launch state, not a failure, which is why it is an `Option` and not an error. | ||
| #[tauri::command] | ||
| pub fn server_url(vault: State<'_, Vault>) -> Result<Option<String>, String> { | ||
| crate::server::read(&vault.paths.server()).map_err(|_| failure("unreadable address")) | ||
| } | ||
|
|
||
| /// Records the delivery service, and answers with the form that was stored. | ||
| /// | ||
| /// The answer is the normalised address rather than `()`, so the page uses exactly what the file | ||
| /// holds: the two would otherwise differ by a trailing slash or a default port, and the client | ||
| /// would build its URLs from a string the next launch does not agree with. | ||
| /// | ||
| /// The message on refusal is shown to the person typing, so it says what is wrong with the | ||
| /// address rather than that something is — see [`crate::server::normalise`]. | ||
| #[tauri::command] | ||
| pub fn server_set(url: String, vault: State<'_, Vault>) -> Result<String, String> { | ||
| crate::server::write(&vault.paths.server(), &url) | ||
|
Comment on lines
+144
to
+146
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For a packaged user who chooses “Erase this identity” in order to leave the selected server—the new setup screen explicitly describes erasure as the only exit—the erasure path only calls Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| /// Installs the vault into the application. | ||
| /// | ||
| /// Fails loudly if the secrets can be neither read nor created. That is deliberate: starting | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In every matrix entry this runs after a fresh checkout but without
pnpm install, whiletauri.conf.jsonmakescargo tauri buildinvokepnpm --dir web build. I reproduced that command from a clean checkout: it exits withTS2688, reports thatnode_modulesis missing, and suggests installing dependencies.pnpm run --helpalso describes the command only as running an existing package script, not installing its dependencies. Consequently both tagged releases and manual rehearsals fail before producing any installer; add the same frozen-lockfile install step used by the Android, iOS, and test workflows.Useful? React with 👍 / 👎.