T26: a release's macOS disk image is signed with the owner's Developer ID and notarized: mac-app.sh signs under the hardened runtime and notarizes and staples the image when given an identity and the App Store Connect key; the Release workflow, dispatched by hand, runs it on the macos-signing runner and puts the image on the draft through release-asset.sh
This commit is contained in:
7 files changed
+105
-9
No files matched your search
@@ -0,0 +1,33 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
# Dispatched once the version's draft release holds the Windows and Linux builds.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
macos:
|
||||||
|
# The owner's login session, whose keychain holds the Developer ID identity.
|
||||||
|
runs-on: macos-signing
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
# The runner's PATH lacks the host's rustup.
|
||||||
|
- run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||||
|
- run: rustup toolchain install --no-self-update
|
||||||
|
- name: Build, sign and notarize the disk image
|
||||||
|
env:
|
||||||
|
SIGN_IDENTITY: "Developer ID Application: Yang Zhang (9PDD8M2SMS)"
|
||||||
|
NOTARY_KEY: ${{ runner.temp }}/notary.p8
|
||||||
|
NOTARY_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
|
||||||
|
NOTARY_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
|
||||||
|
NOTARY_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
|
||||||
|
run: |
|
||||||
|
trap 'rm -f "$NOTARY_KEY"' EXIT
|
||||||
|
(umask 077 && printf '%s' "$NOTARY_KEY_P8" > "$NOTARY_KEY")
|
||||||
|
scripts/mac-app.sh
|
||||||
|
- name: Put the disk image on the release
|
||||||
|
env:
|
||||||
|
RELEASE_API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||||
|
RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
version=$(cargo pkgid)
|
||||||
|
scripts/release-asset.sh "target/release/ELYTerminal-${version##*[#@]}.dmg"
|
||||||
@@ -22,9 +22,10 @@ ELYTerminal. A terminal on GPUI and Ely components. `PRD.md` says what it does;
|
|||||||
- mouse gestures handed to gpui's view, at points from the content's top-left, modifiers as for keys: `click@x,y`, `click2@`, `click3@`, `rclick@`, `mclick@`, `drag@x,y@x,y`, `move@x,y`, the steps `ldown@`, `lup@`, `ldrag@`, `rdown@`, `rup@`, `mdown@`, `mup@`, and `scrollup@x,y@lines`, `scrolldown@x,y@lines`.
|
- mouse gestures handed to gpui's view, at points from the content's top-left, modifiers as for keys: `click@x,y`, `click2@`, `click3@`, `rclick@`, `mclick@`, `drag@x,y@x,y`, `move@x,y`, the steps `ldown@`, `lup@`, `ldrag@`, `rdown@`, `rup@`, `mdown@`, `mup@`, and `scrollup@x,y@lines`, `scrolldown@x,y@lines`.
|
||||||
- `scripts/check.sh`: fmt, clippy `-D warnings`, tests, the 500-line rule.
|
- `scripts/check.sh`: fmt, clippy `-D warnings`, tests, the 500-line rule.
|
||||||
- `scripts/linux.sh ARGS` runs `cargo ARGS` on the working tree in a Linux container, the build kept in Docker volumes; `scripts/linux.sh test --locked` runs the tests as a user, not root, as CI does. The tree goes in as a tar stream, every file dated now: Colima's shared folder can show the VM a file as it was before an edit, and cargo judges by date, so a tree older than the last build would reuse that build. It needs a Docker daemon: on macOS, Colima (`colima start`).
|
- `scripts/linux.sh ARGS` runs `cargo ARGS` on the working tree in a Linux container, the build kept in Docker volumes; `scripts/linux.sh test --locked` runs the tests as a user, not root, as CI does. The tree goes in as a tar stream, every file dated now: Colima's shared folder can show the VM a file as it was before an edit, and cargo judges by date, so a tree older than the last build would reuse that build. It needs a Docker daemon: on macOS, Colima (`colima start`).
|
||||||
- `scripts/mac-app.sh` builds `target/release/ELYTerminal.app` from a release build, signed ad hoc, and `ELYTerminal-VERSION.dmg` beside it, the app next to a link to Applications. Its icon: `examples/icons.rs` renders `assets/icons/elyterminal-macos.svg` into an iconset, which `iconutil` packs.
|
- `scripts/mac-app.sh` builds `target/release/ELYTerminal.app` from a release build, signed ad hoc, and `ELYTerminal-VERSION.dmg` beside it, the app next to a link to Applications. Given `SIGN_IDENTITY` and the App Store Connect key, `NOTARY_KEY` (its .p8 file), `NOTARY_KEY_ID` and `NOTARY_ISSUER`, it signs with that identity under the hardened runtime, then notarizes and staples the image, and it stops before building when one is missing or no keychain holds the identity. Its icon: `examples/icons.rs` renders `assets/icons/elyterminal-macos.svg` into an iconset, which `iconutil` packs.
|
||||||
- `scripts/windows-zip.ps1`, on Windows with Visual Studio's C++ tools, builds `elyterminal.exe` with its icon and zips it as `ELYTerminal-VERSION-windows-ARCH.zip` in `target/release`. After an edit to the figure, `cargo run --example icons -- ico assets/icons/elyterminal.svg assets/icons/elyterminal.ico` renders the icon again.
|
- `scripts/windows-zip.ps1`, on Windows with Visual Studio's C++ tools, builds `elyterminal.exe` with its icon and zips it as `ELYTerminal-VERSION-windows-ARCH.zip` in `target/release`. After an edit to the figure, `cargo run --example icons -- ico assets/icons/elyterminal.svg assets/icons/elyterminal.ico` renders the icon again.
|
||||||
- `scripts/linux-tar.sh` builds the release in Docker on `rust:1.95.0-bookworm` and packs it with `com.zacharyzhang.elyterminal.desktop` and the icon as `ELYTerminal-VERSION-linux-ARCH.tar.gz` in `target/release`.
|
- `scripts/linux-tar.sh` builds the release in Docker on `rust:1.95.0-bookworm` and packs it with `com.zacharyzhang.elyterminal.desktop` and the icon as `ELYTerminal-VERSION-linux-ARCH.tar.gz` in `target/release`.
|
||||||
|
- `scripts/release-asset.sh FILE` puts FILE on the Gitea release of this version, a draft too, in place of a file of its name; `RELEASE_API` and `RELEASE_TOKEN` say where and as whom. The Release workflow, `.github/workflows/release.yml`, dispatched by hand, builds the signed and notarized disk image on the `macos-signing` runner and puts it on the release.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
@@ -83,8 +84,9 @@ ELYTerminal. A terminal on GPUI and Ely components. `PRD.md` says what it does;
|
|||||||
- 2026-10-15: the macOS menu bar is the PRD's: ELYTerminal (Settings…, Quit), Shell (New Session, Close Session), Edit (Copy, Paste, Select All, Find), View (Toggle Sessions, Toggle Right Panel, Bigger, Smaller, Reset Size), Window (Minimize, Zoom, then the windows macOS lists). An item shows the key bound to its action, so the menus are set after the bindings; Copy, Paste and Select All go through AppKit's `copy:`, `paste:` and `selectAll:`, as gpui's `OsAction` maps them. They are Ely's text input actions, which `forms` exports for this, and the terminal handles them too: gpui sends a menu's action to what holds focus and enables the item only where a handler waits, so one action serves the terminal, find and every field. The new keys are Ghostty's: Cmd-Q, Cmd-A, Cmd-= and Cmd-+, Cmd-minus, Cmd-0, Cmd-M. Off macOS Quit and Select All take Ctrl-Shift, since Ctrl with a letter types a control byte; the font's size takes plain Ctrl with =, +, minus and 0, which type none, as in Ghostty, Alacritty and Windows Terminal; Minimize has no key there. Bigger and Smaller move every session's font a point, inside the Size range, and Reset Size goes back to the setting; nothing saves the change, as in Ghostty. Select All runs from the first character in the history to the last on the screen, the blanks around them left out, as Ghostty's, though a space under a combining mark shows a character and counts as one; copy on select takes it, and a blank grid selects nothing.
|
- 2026-10-15: the macOS menu bar is the PRD's: ELYTerminal (Settings…, Quit), Shell (New Session, Close Session), Edit (Copy, Paste, Select All, Find), View (Toggle Sessions, Toggle Right Panel, Bigger, Smaller, Reset Size), Window (Minimize, Zoom, then the windows macOS lists). An item shows the key bound to its action, so the menus are set after the bindings; Copy, Paste and Select All go through AppKit's `copy:`, `paste:` and `selectAll:`, as gpui's `OsAction` maps them. They are Ely's text input actions, which `forms` exports for this, and the terminal handles them too: gpui sends a menu's action to what holds focus and enables the item only where a handler waits, so one action serves the terminal, find and every field. The new keys are Ghostty's: Cmd-Q, Cmd-A, Cmd-= and Cmd-+, Cmd-minus, Cmd-0, Cmd-M. Off macOS Quit and Select All take Ctrl-Shift, since Ctrl with a letter types a control byte; the font's size takes plain Ctrl with =, +, minus and 0, which type none, as in Ghostty, Alacritty and Windows Terminal; Minimize has no key there. Bigger and Smaller move every session's font a point, inside the Size range, and Reset Size goes back to the setting; nothing saves the change, as in Ghostty. Select All runs from the first character in the history to the last on the screen, the blanks around them left out, as Ghostty's, though a space under a combining mark shows a character and counts as one; copy on select takes it, and a blank grid selects nothing.
|
||||||
- 2026-10-15: CI runs on self-hosted Gitea runners, each job with what its runner must hold. macOS runs on the host, with fish and PowerShell installed, or the two shell tests fail as they should. Windows runs on the host, with rustup's `cargo` and `rustc` proxies beside `rustup` and Visual Studio's C++ tools. Ubuntu (`ubuntu-24.04`) runs as root in `docker.gitea.com/runner-images:ubuntu-24.04`, installs the libraries gpui links, and runs the tests as a user it makes, since root ignores the file modes they check; its runner serves this repository alone, in a VM of its own, so a build cannot starve other containers. The Linux and Windows jobs build without debuginfo, as `scripts/linux.sh` does: with it, linking gpui's test binaries outgrew that VM's 8 GB. The macOS and Windows jobs run on the owner's own machines, so they skip `Swatinem/rust-cache`: its post step cleans `$CARGO_HOME`, which there is the owner's own, and after every job it deleted `rustup` from `~/.cargo/bin`, leaving its proxies pointing at nothing, and pruned the shared registry; the Linux job keeps it, inside its container. A run that waits on a missing runner stays queued: cancel stale ones before a new runner registers, or it runs every one. The shell tests type a line only once the line editor reads raw keys, canonical mode off: on CI, a line typed before PowerShell's first read was echoed by the terminal and never run. Every job installs the toolchain `rust-toolchain.toml` names with `rustup toolchain install --no-self-update` and never runs `rustup default`, so the owner's machines keep their own default toolchain and rustup; the macOS job puts the host's `~/.cargo/bin` on the runner's PATH, and the Linux container installs rustup first. A toolchain file's components install only with the toolchain: one already there without them makes each cargo call try to download them, so `scripts/linux.sh` and `scripts/linux-tar.sh` add them to their images.
|
- 2026-10-15: CI runs on self-hosted Gitea runners, each job with what its runner must hold. macOS runs on the host, with fish and PowerShell installed, or the two shell tests fail as they should. Windows runs on the host, with rustup's `cargo` and `rustc` proxies beside `rustup` and Visual Studio's C++ tools. Ubuntu (`ubuntu-24.04`) runs as root in `docker.gitea.com/runner-images:ubuntu-24.04`, installs the libraries gpui links, and runs the tests as a user it makes, since root ignores the file modes they check; its runner serves this repository alone, in a VM of its own, so a build cannot starve other containers. The Linux and Windows jobs build without debuginfo, as `scripts/linux.sh` does: with it, linking gpui's test binaries outgrew that VM's 8 GB. The macOS and Windows jobs run on the owner's own machines, so they skip `Swatinem/rust-cache`: its post step cleans `$CARGO_HOME`, which there is the owner's own, and after every job it deleted `rustup` from `~/.cargo/bin`, leaving its proxies pointing at nothing, and pruned the shared registry; the Linux job keeps it, inside its container. A run that waits on a missing runner stays queued: cancel stale ones before a new runner registers, or it runs every one. The shell tests type a line only once the line editor reads raw keys, canonical mode off: on CI, a line typed before PowerShell's first read was echoed by the terminal and never run. Every job installs the toolchain `rust-toolchain.toml` names with `rustup toolchain install --no-self-update` and never runs `rustup default`, so the owner's machines keep their own default toolchain and rustup; the macOS job puts the host's `~/.cargo/bin` on the runner's PATH, and the Linux container installs rustup first. A toolchain file's components install only with the toolchain: one already there without them makes each cargo call try to download them, so `scripts/linux.sh` and `scripts/linux-tar.sh` add them to their images.
|
||||||
- 2026-10-15: on macOS 27 gpui's `Blurred` gives its NSVisualEffectView the `Selection` material, which builds no backdrop layer, so the desktop showed through sharp. `blur/macos` sets the view to `underWindowBackground` whenever the window turns Blurred: a gaussian blur of radius 30, the radius the owner's Ghostty uses; gpui's `updateLayer` still strips the material's tint and saturation. The view's presence proved nothing, so `shot` reads the radius off its backdrop layer.
|
- 2026-10-15: on macOS 27 gpui's `Blurred` gives its NSVisualEffectView the `Selection` material, which builds no backdrop layer, so the desktop showed through sharp. `blur/macos` sets the view to `underWindowBackground` whenever the window turns Blurred: a gaussian blur of radius 30, the radius the owner's Ghostty uses; gpui's `updateLayer` still strips the material's tint and saturation. The view's presence proved nothing, so `shot` reads the radius off its backdrop layer.
|
||||||
- 2026-10-15: the icon is drawn by hand in SVG, flat, so one figure serves both forms: on macOS it stands on a night-purple rounded square on Apple's grid (824 of 1024, radius 185) with sparkles, the gradient grained so it does not band; on Windows and Linux it stands alone, as Papirus draws app icons. The app is `com.zacharyzhang.elyterminal`, after the owner's domain, signed ad hoc: it opens on the Mac that built it, and Gatekeeper asks once on any other.
|
- 2026-10-15: the icon is drawn by hand in SVG, flat, so one figure serves both forms: on macOS it stands on a night-purple rounded square on Apple's grid (824 of 1024, radius 185) with sparkles, the gradient grained so it does not band; on Windows and Linux it stands alone, as Papirus draws app icons. The app is `com.zacharyzhang.elyterminal`, after the owner's domain. A local build is signed ad hoc: it opens on the Mac that built it, and Gatekeeper asks once on any other; a release's is signed with the owner's Developer ID and notarized, so it opens on any Mac.
|
||||||
- 2026-10-15: a release is a Gitea release tagged `vVERSION` with three builds, each from its script: the macOS disk image for Apple silicon, a Windows zip and a Linux tarball for x86_64. Each window names itself `com.zacharyzhang.elyterminal` through `Window::set_app_id` as it opens: on Linux that is Wayland's app id and X11's `WM_CLASS`, which the desktop entry's name and `StartupWMClass` match, so a dock pairs the window with the icon; gpui's X11 windows read no app id from `WindowOptions`.
|
- 2026-10-15: a release is a Gitea release tagged `vVERSION` with three builds, each from its script: the macOS disk image for Apple silicon, a Windows zip and a Linux tarball for x86_64. Each window names itself `com.zacharyzhang.elyterminal` through `Window::set_app_id` as it opens: on Linux that is Wayland's app id and X11's `WM_CLASS`, which the desktop entry's name and `StartupWMClass` match, so a dock pairs the window with the icon; gpui's X11 windows read no app id from `WindowOptions`.
|
||||||
- 2026-10-15: on Windows a release build is a GUI program, so no console window opens beside it; a debug build keeps its console for the log. git then starts with `CREATE_NO_WINDOW`, or each call would open a console. Windows builds link the C runtime statically, so the executable needs no Visual C++ redistributable. gpui's build script embeds its manifest, PerMonitorV2 DPI awareness among it; `build.rs` adds the icon as resource 1, which gpui loads for each window, and stops the build when no resource compiler is found.
|
- 2026-10-15: on Windows a release build is a GUI program, so no console window opens beside it; a debug build keeps its console for the log. git then starts with `CREATE_NO_WINDOW`, or each call would open a console. Windows builds link the C runtime statically, so the executable needs no Visual C++ redistributable. gpui's build script embeds its manifest, PerMonitorV2 DPI awareness among it; `build.rs` adds the icon as resource 1, which gpui loads for each window, and stops the build when no resource compiler is found.
|
||||||
- 2026-10-15: the Linux tarball builds on Debian 12, in `rust:1.95.0-bookworm`: a binary asks for the glibc symbol versions it was linked against, so it is linked against an old glibc, not the builder's. `scripts/linux-tar.sh` prints the glibc its build asks for, and the README names it: 2.35 for v0.1.0, which runs on Ubuntu 22.04.
|
- 2026-10-15: the Linux tarball builds on Debian 12, in `rust:1.95.0-bookworm`: a binary asks for the glibc symbol versions it was linked against, so it is linked against an old glibc, not the builder's. `scripts/linux-tar.sh` prints the glibc its build asks for, and the README names it: 2.35 for v0.1.0, which runs on Ubuntu 22.04.
|
||||||
- 2026-10-15: on Windows gpui answers the system's hit test from the last frame: under the pointer, a `WindowControlArea::Drag` hitbox that nothing occludes makes it the caption, and Windows keeps the press, so no click reaches the app. In v0.1.0 every title bar control was dead so. Ely now occludes the drag region under its window buttons, which then answer as close, maximize and minimize, and under each column header's item row, whose controls get plain presses; the row stays the scroll container, and its title is a drag region of its own.
|
- 2026-10-15: on Windows gpui answers the system's hit test from the last frame: under the pointer, a `WindowControlArea::Drag` hitbox that nothing occludes makes it the caption, and Windows keeps the press, so no click reaches the app. In v0.1.0 every title bar control was dead so. Ely now occludes the drag region under its window buttons, which then answer as close, maximize and minimize, and under each column header's item row, whose controls get plain presses; the row stays the scroll container, and its title is a drag region of its own.
|
||||||
|
- 2026-10-15: a release's macOS disk image comes from the Release workflow, dispatched once the draft holds the Windows and Linux builds. It runs on `macos-signing`, the Mac mini's runner in the owner's login session, whose keychain holds the Developer ID identity; at the owner's choice that runner moved from AgentCompany alone to the owner's level, so every repository reaches it. The job reads the App Store Connect key from the owner's user-level secrets `APPLE_API_ISSUER`, `APPLE_API_KEY_ID` and `APPLE_API_KEY_P8`, writes the .p8 into the runner's temp folder for notarytool alone, and puts the stapled image on the draft through `scripts/release-asset.sh` with the job's own token. One notarization covers the image and the app inside it; the image carries the ticket, and the app copied out finds its own online on its first open.
|
||||||
@@ -129,13 +129,13 @@ Cmd-, opens it; on Windows and Linux, which have no menu bar, so does a gear in
|
|||||||
|
|
||||||
- The icon is Ely, a girl with long pink hair, holding a terminal in front of her.
|
- The icon is Ely, a girl with long pink hair, holding a terminal in front of her.
|
||||||
- macOS: the icon on the rounded square macOS gives app icons. Windows and Linux: the figure alone, no ground, flat, as Papirus draws.
|
- macOS: the icon on the rounded square macOS gives app icons. Windows and Linux: the figure alone, no ground, flat, as Papirus draws.
|
||||||
- `scripts/mac-app.sh` builds `ELYTerminal.app` from a release build with its icon, signed ad hoc, and a disk image holding it beside a link to Applications.
|
- `scripts/mac-app.sh` builds `ELYTerminal.app` from a release build with its icon, signed ad hoc, or for a release with Developer ID and notarized, and a disk image holding it beside a link to Applications.
|
||||||
|
|
||||||
## 15. Release
|
## 15. Release
|
||||||
|
|
||||||
- A release on Gitea, tagged `vVERSION`, carries three builds: the macOS disk image (Apple silicon), a Windows zip (x86_64) and a Linux tarball (x86_64).
|
- A release on Gitea, tagged `vVERSION`, carries three builds: the macOS disk image (Apple silicon, signed with Developer ID and notarized), a Windows zip (x86_64) and a Linux tarball (x86_64).
|
||||||
- The Windows executable carries the icon. The Linux tarball carries the icon and a desktop entry, and the window names itself after it, `com.zacharyzhang.elyterminal`, as the macOS bundle does.
|
- The Windows executable carries the icon. The Linux tarball carries the icon and a desktop entry, and the window names itself after it, `com.zacharyzhang.elyterminal`, as the macOS bundle does.
|
||||||
- Each build comes from its platform's script: `scripts/mac-app.sh`, `scripts/windows-zip.ps1`, `scripts/linux-tar.sh`.
|
- Each build comes from its platform's script: `scripts/mac-app.sh`, `scripts/windows-zip.ps1`, `scripts/linux-tar.sh`. The macOS one runs on the signing runner, through the Release workflow.
|
||||||
|
|
||||||
## Deferred
|
## Deferred
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ A terminal for macOS, Windows and Linux, in Rust on GPUI and Ely components. Ses
|
|||||||
|
|
||||||
A release on Gitea carries three builds.
|
A release on Gitea carries three builds.
|
||||||
|
|
||||||
- macOS 11 or later, Apple silicon: open `ELYTerminal-VERSION.dmg` and drag ELYTerminal into Applications. The app is signed ad hoc, not notarized, so macOS stops its first open: in System Settings, Privacy & Security, press Open Anyway.
|
- macOS 11 or later, Apple silicon: open `ELYTerminal-VERSION.dmg` and drag ELYTerminal into Applications. The app is signed with Developer ID and notarized.
|
||||||
- Windows 10 or later, x86_64: unzip `ELYTerminal-VERSION-windows-x86_64.zip` and run `elyterminal.exe`. It is unsigned; if SmartScreen stops it, press More info, then Run anyway.
|
- Windows 10 or later, x86_64: unzip `ELYTerminal-VERSION-windows-x86_64.zip` and run `elyterminal.exe`. It is unsigned; if SmartScreen stops it, press More info, then Run anyway.
|
||||||
- Linux, x86_64, glibc 2.35 or later, with libxkbcommon, libxkbcommon-x11 and libxcb:
|
- Linux, x86_64, glibc 2.35 or later, with libxkbcommon, libxkbcommon-x11 and libxcb:
|
||||||
|
|
||||||
|
|||||||
@@ -71,4 +71,4 @@ Progress truth. Top to bottom, one at a time. A task is ticked only after its co
|
|||||||
|
|
||||||
## 16. Fixes from the owner's first run
|
## 16. Fixes from the owner's first run
|
||||||
|
|
||||||
- [ ] T26 On Windows every title bar control takes its press, Ely's window buttons too: in Ely, window buttons and header items occlude the drag region; the Git and Files switch moves below the title bar, centered; on Windows and Linux a gear in the title bar opens Settings; on Windows Ctrl-V pastes, as in Windows Terminal; the pointer over the terminal is the arrow; the settings window drops General, whose Shell and Start in lead Terminal, which lists every shortcut, and its categories and page scroll apart; release v0.1.1 with the three builds.
|
- [ ] T26 On Windows every title bar control takes its press, Ely's window buttons too: in Ely, window buttons and header items occlude the drag region; the Git and Files switch moves below the title bar, centered; on Windows and Linux a gear in the title bar opens Settings; on Windows Ctrl-V pastes, as in Windows Terminal; the pointer over the terminal is the arrow; the settings window drops General, whose Shell and Start in lead Terminal, which lists every shortcut, and its categories and page scroll apart; the release's macOS disk image signed with Developer ID and notarized on the signing runner; release v0.1.1 with the three builds.
|
||||||
+31
-2
@@ -1,7 +1,18 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# mac-app.sh: ELYTerminal.app in target/release, signed ad hoc, and its disk image.
|
# mac-app.sh: ELYTerminal.app in target/release and its disk image, signed ad hoc, or by SIGN_IDENTITY and notarized.
|
||||||
set -eu
|
set -eu
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
sign=${SIGN_IDENTITY:-}
|
||||||
|
if [ -n "$sign" ]; then
|
||||||
|
[ -s "${NOTARY_KEY:-}" ] && [ -n "${NOTARY_KEY_ID:-}" ] && [ -n "${NOTARY_ISSUER:-}" ] || {
|
||||||
|
echo "mac-app: SIGN_IDENTITY needs NOTARY_KEY (a .p8 file), NOTARY_KEY_ID and NOTARY_ISSUER" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
security find-identity -v -p codesigning | grep -q -F "\"$sign\"" || {
|
||||||
|
echo "mac-app: no valid identity \"$sign\" in the keychains" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
cargo build --release --locked
|
cargo build --release --locked
|
||||||
version=$(cargo pkgid)
|
version=$(cargo pkgid)
|
||||||
version=${version##*[#@]}
|
version=${version##*[#@]}
|
||||||
@@ -38,11 +49,29 @@ cat > "$app/Contents/Info.plist" <<EOF
|
|||||||
</plist>
|
</plist>
|
||||||
EOF
|
EOF
|
||||||
plutil -lint -s "$app/Contents/Info.plist"
|
plutil -lint -s "$app/Contents/Info.plist"
|
||||||
codesign --force --sign - "$app"
|
if [ -n "$sign" ]; then
|
||||||
|
codesign --force --options runtime --timestamp --sign "$sign" "$app"
|
||||||
|
else
|
||||||
|
codesign --force --sign - "$app"
|
||||||
|
fi
|
||||||
mkdir "$work/disk"
|
mkdir "$work/disk"
|
||||||
ditto "$app" "$work/disk/ELYTerminal.app"
|
ditto "$app" "$work/disk/ELYTerminal.app"
|
||||||
ln -s /Applications "$work/disk/Applications"
|
ln -s /Applications "$work/disk/Applications"
|
||||||
dmg=$out/ELYTerminal-$version.dmg
|
dmg=$out/ELYTerminal-$version.dmg
|
||||||
hdiutil create -quiet -volname ELYTerminal -srcfolder "$work/disk" -ov -format UDZO "$dmg"
|
hdiutil create -quiet -volname ELYTerminal -srcfolder "$work/disk" -ov -format UDZO "$dmg"
|
||||||
|
if [ -n "$sign" ]; then
|
||||||
|
codesign --force --timestamp --sign "$sign" "$dmg"
|
||||||
|
notary() { xcrun notarytool "$@" --key "$NOTARY_KEY" --key-id "$NOTARY_KEY_ID" --issuer "$NOTARY_ISSUER"; }
|
||||||
|
notary submit "$dmg" --wait --output-format json > "$work/notary.json" || true
|
||||||
|
status=$(plutil -extract status raw -o - "$work/notary.json" 2>/dev/null || echo none)
|
||||||
|
echo "mac-app: notarization $status"
|
||||||
|
if [ "$status" != Accepted ]; then
|
||||||
|
cat "$work/notary.json" >&2
|
||||||
|
id=$(plutil -extract id raw -o - "$work/notary.json" 2>/dev/null) && notary log "$id" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
xcrun stapler staple "$dmg"
|
||||||
|
spctl --assess --type open --context context:primary-signature --verbose "$dmg"
|
||||||
|
fi
|
||||||
echo "mac-app: $app"
|
echo "mac-app: $app"
|
||||||
echo "mac-app: $dmg"
|
echo "mac-app: $dmg"
|
||||||
Executable
+32
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# release-asset.sh FILE: puts FILE on the Gitea release of this version, a draft too, in place of one of its name.
|
||||||
|
set -eu
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
file=$1
|
||||||
|
[ -f "$file" ] || { echo "release-asset: no file $file" >&2; exit 1; }
|
||||||
|
: "${RELEASE_API:?release-asset: RELEASE_API names the repository API, https://HOST/api/v1/repos/OWNER/REPO}"
|
||||||
|
: "${RELEASE_TOKEN:?release-asset: RELEASE_TOKEN is a token that may edit the releases}"
|
||||||
|
version=$(cargo pkgid)
|
||||||
|
version=${version##*[#@]}
|
||||||
|
name=$(basename "$file")
|
||||||
|
auth="Authorization: token $RELEASE_TOKEN"
|
||||||
|
work=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$work"' EXIT
|
||||||
|
curl -fsS -H "$auth" "$RELEASE_API/releases?limit=50" > "$work/releases.json"
|
||||||
|
ids=$(python3 -c '
|
||||||
|
import json, sys
|
||||||
|
tag, name, path = sys.argv[1:]
|
||||||
|
found = [r for r in json.load(open(path)) if r["tag_name"] == tag]
|
||||||
|
if len(found) != 1:
|
||||||
|
sys.exit(f"release-asset: {len(found)} releases tagged {tag}")
|
||||||
|
print(found[0]["id"], *(a["id"] for a in found[0]["assets"] if a["name"] == name))
|
||||||
|
' "v$version" "$name" "$work/releases.json")
|
||||||
|
set -- $ids
|
||||||
|
release=$1
|
||||||
|
shift
|
||||||
|
for old in "$@"; do
|
||||||
|
curl -fsS -X DELETE -H "$auth" "$RELEASE_API/releases/$release/assets/$old"
|
||||||
|
echo "release-asset: removed the old $name"
|
||||||
|
done
|
||||||
|
curl -fsS -H "$auth" -F "attachment=@$file" "$RELEASE_API/releases/$release/assets?name=$name" > /dev/null
|
||||||
|
echo "release-asset: $name on release $release, v$version"
|
||||||
Reference in new issue
Block a user