Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .docs/scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
- `bun run build` — Builds contracts, web app, and server through Turbo.
- `bun run typecheck` — Strict TypeScript checks for all packages.
- `bun run test` — Runs workspace tests.
- `bun run dist:desktop:artifact -- --platform <mac|linux|win> --target <target> --arch <arch>` — Builds a desktop artifact for a specific platform/target/arch.
- `bun run dist:desktop:artifact -- --platform <mac|linux|win> --target <target[,target2]> --arch <arch>` — Builds a desktop artifact for a specific platform/target/arch.
- `bun run dist:desktop:dmg` — Builds a shareable macOS `.dmg` into `./release`.
- `bun run dist:desktop:dmg:x64` — Builds an Intel macOS `.dmg`.
- `bun run dist:desktop:linux` — Builds a Linux AppImage into `./release`.
- `bun run dist:desktop:linux` — Builds Linux `AppImage`, `.deb`, and `.rpm` artifacts into `./release`.
- `bun run dist:desktop:linux:appimage` — Builds only the Linux AppImage.
- `bun run dist:desktop:linux:deb` — Builds only the Linux `.deb`.
- `bun run dist:desktop:linux:rpm` — Builds only the Linux `.rpm`.
- `bun run dist:desktop:linux:rpm:podman` — Builds the Linux `.rpm` inside a Podman container, useful on Ubuntu hosts that do not have `rpmbuild` installed.
- `bun run dist:desktop:win` — Builds a Windows NSIS installer into `./release`.

## Desktop `.dmg` packaging notes
Expand Down
12 changes: 10 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile

- name: Install Linux packaging tools
if: matrix.platform == 'linux'
run: sudo apt-get update && sudo apt-get install -y rpm

- name: Lint
run: bun run lint

Expand Down Expand Up @@ -95,10 +99,10 @@ jobs:
platform: mac
target: dmg
arch: x64
- label: Linux x64
- label: Linux x64 packages
runner: ubuntu-24.04
platform: linux
target: AppImage
target: AppImage,deb,rpm
arch: x64
- label: Windows x64
runner: windows-2022
Expand Down Expand Up @@ -202,6 +206,8 @@ jobs:
"release/*.dmg" \
"release/*.zip" \
"release/*.AppImage" \
"release/*.deb" \
"release/*.rpm" \
"release/*.exe" \
"release/*.blockmap" \
"release/latest*.yml"; do
Expand Down Expand Up @@ -298,6 +304,8 @@ jobs:
release-assets/*.dmg
release-assets/*.zip
release-assets/*.AppImage
release-assets/*.deb
release-assets/*.rpm
release-assets/*.exe
release-assets/*.blockmap
release-assets/latest*.yml
Expand Down
14 changes: 14 additions & 0 deletions DEBIAN/control
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Package: t3code
Version: 0.0.15
License: unknown
Vendor: T3 Tools <opensource@t3.tools>
Architecture: amd64
Maintainer: T3 Tools <opensource@t3.tools>
Installed-Size: 492821
Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0
Recommends: libappindicator3-1
Section: default
Priority: optional
Homepage: https://github.com/pingdotgg/t3code
Description: T3 Code
T3 Code
285 changes: 285 additions & 0 deletions DEBIAN/md5sums

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions DEBIAN/postinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/bash

if type update-alternatives >/dev/null 2>&1; then
# Remove previous link if it doesn't use update-alternatives
if [ -L '/usr/bin/t3code' -a -e '/usr/bin/t3code' -a "`readlink '/usr/bin/t3code'`" != '/etc/alternatives/t3code' ]; then
rm -f '/usr/bin/t3code'
fi
update-alternatives --install '/usr/bin/t3code' 't3code' '/opt/t3code/t3code' 100 || ln -sf '/opt/t3code/t3code' '/usr/bin/t3code'
else
ln -sf '/opt/t3code/t3code' '/usr/bin/t3code'
fi

# Check if user namespaces are supported by the kernel and working with a quick test:
if ! { [[ -L /proc/self/ns/user ]] && unshare --user true; }; then
# Use SUID chrome-sandbox only on systems without user namespaces:
chmod 4755 '/opt/t3code/chrome-sandbox' || true
else
chmod 0755 '/opt/t3code/chrome-sandbox' || true
fi

if hash update-mime-database 2>/dev/null; then
update-mime-database /usr/share/mime || true
fi

if hash update-desktop-database 2>/dev/null; then
update-desktop-database /usr/share/applications || true
fi

# Install apparmor profile. (Ubuntu 24+)
# First check if the version of AppArmor running on the device supports our profile.
# This is in order to keep backwards compatibility with Ubuntu 22.04 which does not support abi/4.0.
# In that case, we just skip installing the profile since the app runs fine without it on 22.04.
#
# Those apparmor_parser flags are akin to performing a dry run of loading a profile.
# https://wiki.debian.org/AppArmor/HowToUse#Dumping_profiles
#
# Unfortunately, at the moment AppArmor doesn't have a good story for backwards compatibility.
# https://askubuntu.com/questions/1517272/writing-a-backwards-compatible-apparmor-profile
if apparmor_status --enabled > /dev/null 2>&1; then
APPARMOR_PROFILE_SOURCE='/opt/t3code/resources/apparmor-profile'
APPARMOR_PROFILE_TARGET='/etc/apparmor.d/t3code'
if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then
cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET"

# Updating the current AppArmor profile is not possible and probably not meaningful in a chroot'ed environment.
# Use cases are for example environments where images for clients are maintained.
# There, AppArmor might correctly be installed, but live updating makes no sense.
if ! { [ -x '/usr/bin/ischroot' ] && /usr/bin/ischroot; } && hash apparmor_parser 2>/dev/null; then
# Extra flags taken from dh_apparmor:
# > By using '-W -T' we ensure that any abstraction updates are also pulled in.
# https://wiki.debian.org/AppArmor/Contribute/FirstTimeProfileImport
apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET"
fi
else
echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile"
fi
fi
15 changes: 15 additions & 0 deletions DEBIAN/postrm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

# Delete the link to the binary
if type update-alternatives >/dev/null 2>&1; then
update-alternatives --remove 't3code' '/opt/t3code/t3code'
else
rm -f '/usr/bin/t3code'
fi

APPARMOR_PROFILE_DEST='/etc/apparmor.d/t3code'

# Remove apparmor profile.
if [ -f "$APPARMOR_PROFILE_DEST" ]; then
rm -f "$APPARMOR_PROFILE_DEST"
fi
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ brew install --cask t3-code
yay -S t3code-bin
```

#### Ubuntu / Debian

Download the latest `.deb` from [GitHub Releases](https://github.com/pingdotgg/t3code/releases) and install it with:

```bash
sudo apt install ./T3-Code-*.deb
```

#### Fedora / RHEL

Download the latest `.rpm` from [GitHub Releases](https://github.com/pingdotgg/t3code/releases) and install it with:

```bash
sudo dnf install ./T3-Code-*.rpm
```

## Some notes

We are very very early in this project. Expect bugs.
Expand Down
2 changes: 0 additions & 2 deletions apps/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,6 @@ function handleCheckForUpdatesMenuClick(): void {
isDevelopment,
isPackaged: app.isPackaged,
platform: process.platform,
appImage: process.env.APPIMAGE,
disabledByEnv: process.env.T3CODE_DISABLE_AUTO_UPDATE === "1",
});
if (disabledReason) {
Expand Down Expand Up @@ -784,7 +783,6 @@ function shouldEnableAutoUpdates(): boolean {
isDevelopment,
isPackaged: app.isPackaged,
platform: process.platform,
appImage: process.env.APPIMAGE,
disabledByEnv: process.env.T3CODE_DISABLE_AUTO_UPDATE === "1",
}) === null
);
Expand Down
7 changes: 2 additions & 5 deletions apps/desktop/src/updateState.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ describe("getAutoUpdateDisabledReason", () => {
isDevelopment: true,
isPackaged: false,
platform: "darwin",
appImage: undefined,
disabledByEnv: false,
}),
).toContain("packaged production builds");
Expand All @@ -81,22 +80,20 @@ describe("getAutoUpdateDisabledReason", () => {
isDevelopment: false,
isPackaged: true,
platform: "darwin",
appImage: undefined,
disabledByEnv: true,
}),
).toContain("T3CODE_DISABLE_AUTO_UPDATE");
});

it("reports linux non-AppImage builds as disabled", () => {
it("allows packaged Linux builds when not otherwise disabled", () => {
expect(
getAutoUpdateDisabledReason({
isDevelopment: false,
isPackaged: true,
platform: "linux",
appImage: undefined,
disabledByEnv: false,
}),
).toContain("AppImage");
).toBeNull();
});
});

Expand Down
4 changes: 0 additions & 4 deletions apps/desktop/src/updateState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export function getAutoUpdateDisabledReason(args: {
isDevelopment: boolean;
isPackaged: boolean;
platform: NodeJS.Platform;
appImage?: string | undefined;
disabledByEnv: boolean;
}): string | null {
if (args.isDevelopment || !args.isPackaged) {
Expand All @@ -41,8 +40,5 @@ export function getAutoUpdateDisabledReason(args: {
if (args.disabledByEnv) {
return "Automatic updates are disabled by the T3CODE_DISABLE_AUTO_UPDATE setting.";
}
if (args.platform === "linux" && !args.appImage) {
return "Automatic updates on Linux require running the AppImage build.";
}
return null;
}
26 changes: 18 additions & 8 deletions apps/marketing/src/pages/download.astro
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import { RELEASES_URL } from "../lib/releases";
<h2 class="platform-name">macOS</h2>
</div>
<div class="download-cards">
<a class="download-card" data-asset="arm64.dmg" href={RELEASES_URL}>
<a class="download-card" data-asset-pattern="-arm64\\.dmg$" href={RELEASES_URL}>
<span class="card-arch">Apple Silicon (arm64)</span>
<span class="card-format">.dmg</span>
</a>
<a class="download-card" data-asset="x64.dmg" href={RELEASES_URL}>
<a class="download-card" data-asset-pattern="-x64\\.dmg$" href={RELEASES_URL}>
<span class="card-arch">Intel (x64)</span>
<span class="card-format">.dmg</span>
</a>
Expand All @@ -36,7 +36,7 @@ import { RELEASES_URL } from "../lib/releases";
<h2 class="platform-name">Windows</h2>
</div>
<div class="download-cards">
<a class="download-card" data-asset="x64.exe" href={RELEASES_URL}>
<a class="download-card" data-asset-pattern="-x64\\.exe$" href={RELEASES_URL}>
<span class="card-arch">Windows 10, 11</span>
<span class="card-format">.exe</span>
</a>
Expand All @@ -50,10 +50,18 @@ import { RELEASES_URL } from "../lib/releases";
<h2 class="platform-name">Linux</h2>
</div>
<div class="download-cards">
<a class="download-card" data-asset="x86_64.AppImage" href={RELEASES_URL}>
<span class="card-arch">x86_64</span>
<a class="download-card" data-asset-pattern="-(x64|x86_64)\\.AppImage$" href={RELEASES_URL}>
<span class="card-arch">Portable Linux</span>
<span class="card-format">AppImage</span>
</a>
<a class="download-card" data-asset-pattern="-(x64|amd64)\\.deb$" href={RELEASES_URL}>
<span class="card-arch">Ubuntu / Debian</span>
<span class="card-format">.deb</span>
</a>
<a class="download-card" data-asset-pattern="-(x64|x86_64)\\.rpm$" href={RELEASES_URL}>
<span class="card-arch">Fedora / RHEL</span>
<span class="card-format">.rpm</span>
</a>
</div>
</section>
</div>
Expand Down Expand Up @@ -87,10 +95,12 @@ import { RELEASES_URL } from "../lib/releases";
}

cards.forEach((card) => {
const suffix = card.dataset.asset;
if (!suffix) return;
const pattern = card.dataset.assetPattern;
if (!pattern) return;

const matcher = new RegExp(pattern);

const match = (release.assets ?? []).find((a) => a.name.endsWith(`-${suffix}`));
const match = (release.assets ?? []).find((a) => matcher.test(a.name));
if (match) {
card.href = match.browser_download_url;
} else {
Expand Down
Loading
Loading