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
193 changes: 193 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
name: nightly

on:
workflow_dispatch:
inputs:
branch:
description: Branch to build
required: true
default: main
type: string

concurrency:
group: nightly-${{ inputs.branch }}
cancel-in-progress: false

permissions:
contents: read

jobs:
preflight:
name: preflight
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 15
outputs:
nightly_id: ${{ steps.nightly.outputs.nightly_id }}
nightly_version: ${{ steps.nightly.outputs.nightly_version }}
source_ref: ${{ steps.nightly.outputs.source_ref }}
source_sha: ${{ steps.nightly.outputs.source_sha }}

steps:
- name: Validate branch
shell: bash
env:
INPUT_BRANCH: ${{ inputs.branch }}
run: |
source_ref="${INPUT_BRANCH}"
if [[ -z "$source_ref" ]]; then
echo "Branch is required." >&2
exit 1
fi

if [[ "$source_ref" == refs/* || "$source_ref" == origin/* ]]; then
echo "Enter a branch name such as main or feature/nightly, not $source_ref." >&2
exit 1
fi

git check-ref-format --branch "$source_ref" >/dev/null

- name: Checkout source branch
uses: actions/checkout@v4
with:
ref: ${{ inputs.branch }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Resolve nightly metadata
id: nightly
shell: bash
env:
INPUT_BRANCH: ${{ inputs.branch }}
RUN_NUMBER: ${{ github.run_number }}
run: |
stamp="$(date -u +'%Y%m%d')"
base_version="$(node -p "require('./package.json').version.replace(/[-+].*$/, '')")"
nightly_id="${stamp}.${RUN_NUMBER}"
nightly_version="${base_version}-nightly.${nightly_id}"

{
echo "nightly_id=$nightly_id"
echo "nightly_version=$nightly_version"
echo "source_ref=$INPUT_BRANCH"
echo "source_sha=$(git rev-parse HEAD)"
} >> "$GITHUB_OUTPUT"

build:
name: ${{ matrix.label }}
runs-on: ${{ matrix.os }}
needs: preflight
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- label: windows-x64
os: blacksmith-2vcpu-windows-2025
builder_args: "--win nsis portable --x64"
artifact_paths: |
dist-release/*-x64.exe
dist-release/latest*.yml
dist-release/*.blockmap
- label: windows-arm64
os: blacksmith-2vcpu-windows-2025
builder_args: "--win nsis portable --arm64"
artifact_paths: |
dist-release/*-arm64.exe
- label: macos-x64
os: blacksmith-6vcpu-macos-15
builder_args: "--mac dmg zip --x64"
artifact_paths: |
dist-release/*.dmg
dist-release/*-x64.zip
- label: macos-arm64
os: blacksmith-6vcpu-macos-15
builder_args: "--mac dmg zip --arm64"
artifact_paths: |
dist-release/*.dmg
dist-release/*-arm64.zip
- label: linux-x64
os: blacksmith-2vcpu-ubuntu-2404
builder_args: "--linux AppImage deb --x64"
artifact_paths: |
dist-release/*-x86_64.AppImage
dist-release/*-linux-x64.AppImage
dist-release/*-amd64.deb
dist-release/*-linux-x64.deb
dist-release/latest-linux.yml
- label: linux-arm64
os: blacksmith-2vcpu-ubuntu-2404-arm
builder_args: "--linux AppImage deb --arm64"
artifact_paths: |
dist-release/*-arm64.AppImage
dist-release/*-arm64.deb
dist-release/latest-linux-arm64.yml

env:
CSC_IDENTITY_AUTO_DISCOVERY: "false"
ELECTRON_CACHE: ${{ github.workspace }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ github.workspace }}/.cache/electron-builder
NIGHTLY_VERSION: ${{ needs.preflight.outputs.nightly_version }}
npm_config_audit: "false"
npm_config_fund: "false"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing USE_SYSTEM_FPM arm64

Medium Severity

The nightly build job installs system fpm on the linux-arm64 matrix row but never sets USE_SYSTEM_FPM, unlike the existing release workflow. electron-builder then tends to use its bundled x86 fpm on ARM runners, so Linux arm64 .deb packaging in nightly can fail even after the gem install step.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1558bcd. Configure here.

USE_SYSTEM_FPM: ${{ matrix.label == 'linux-arm64' && 'true' || 'false' }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.preflight.outputs.source_sha }}
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: package-lock.json

- name: Cache Electron binaries
uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/.cache/electron
${{ github.workspace }}/.cache/electron-builder
key: ${{ runner.os }}-electron-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-electron-

- name: Install Linux packaging packages
if: runner.os == 'Linux'
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends fakeroot rpm

- name: Install FPM for arm64 deb builds
if: matrix.label == 'linux-arm64'
run: |
sudo apt-get install -y ruby ruby-dev build-essential
sudo gem install fpm

- name: Set nightly package version
run: node tools/sync-release-version.mjs "$NIGHTLY_VERSION"

- name: Install dependencies
run: npm ci --prefer-offline --no-audit --progress=false

- name: Build app
run: npm run build

- name: Package installers
run: npx electron-builder --publish never ${{ matrix.builder_args }}

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: openstroid-nightly-${{ needs.preflight.outputs.nightly_id }}-${{ matrix.label }}
path: ${{ matrix.artifact_paths }}
if-no-files-found: error
44 changes: 44 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

103 changes: 103 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
description = "OpenStroid";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-electron.url = "github:NixOS/nixpkgs/nixos-25.11";
};

outputs = {
self,
nixpkgs,
nixpkgs-electron,
}: let
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
pkgsFor = system: import nixpkgs {inherit system;};
electronPkgsFor = system:
import nixpkgs-electron {
inherit system;
config.permittedInsecurePackages = ["electron-37.10.3"];
};
linuxElectronConfig = pkgs: electronPackage: {
packages = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [electronPackage];
env = pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isLinux ''
export ELECTRON_SKIP_BINARY_DOWNLOAD=1
export ELECTRON_OVERRIDE_DIST_PATH="${electronPackage}/bin"
export npm_config_electron_skip_binary_download=true
'';
};
in {
devShells = forAllSystems (system: let
pkgs = pkgsFor system;
linuxElectron = linuxElectronConfig pkgs (electronPkgsFor system).electron_37;
in {
default = pkgs.mkShell {
packages = with pkgs;
[
bun
nodejs_22
pkg-config
python3
]
++ linuxElectron.packages
++ lib.optionals stdenv.hostPlatform.isLinux [
fakeroot
rpm
ruby
];
Comment thread
coderabbitai[bot] marked this conversation as resolved.

shellHook =
''
export ELECTRON_CACHE="$PWD/.cache/electron"
export ELECTRON_BUILDER_CACHE="$PWD/.cache/electron-builder"
''
+ linuxElectron.env;
};
});

apps = forAllSystems (system: let
pkgs = pkgsFor system;
linuxElectron = linuxElectronConfig pkgs (electronPkgsFor system).electron_37;
openstroidDev = pkgs.writeShellApplication {
name = "openstroid-dev";
runtimeInputs =
[
pkgs.bun
pkgs.nodejs_22
]
++ linuxElectron.packages;
text =
linuxElectron.env
+ ''
exec bun run dev "$@"
'';
};
in {
default = {
type = "app";
program = "${openstroidDev}/bin/openstroid-dev";
};
});

formatter = forAllSystems (system: let
pkgs = pkgsFor system;
in
pkgs.writeShellApplication {
name = "openstroid-fmt";
runtimeInputs = [pkgs.alejandra];
text = ''
if [ "$#" -eq 0 ]; then
set -- flake.nix
fi

exec alejandra "$@"
'';
});
};
}
12 changes: 12 additions & 0 deletions tools/fix-electron-install.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const distPath = path.join(electronDir, 'dist');
const pathFile = path.join(electronDir, 'path.txt');
const platformPath = getPlatformPath();

function isTruthy(value) {
return /^(1|true|yes)$/i.test(value ?? '');
}

function getPlatformPath() {
const platform = process.env.npm_config_platform || process.platform;

Expand Down Expand Up @@ -66,6 +70,14 @@ async function extractZip(zipPath, destination) {
}

(async () => {
if (
isTruthy(process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) ||
isTruthy(process.env.npm_config_electron_skip_binary_download)
) {
console.log('Skipping Electron binary install because Electron binary downloads are disabled.');
return;
}

if (isInstalled()) {
return;
}
Expand Down