From 2cca0d9ab687ab46ce97641cb46b0a0f120854ff Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Thu, 14 May 2026 14:19:01 -0500 Subject: [PATCH 01/14] fix: update build pipeline and configuration for release process --- .env.example | 15 +- .erb/configs/webpack.config.main.prod.ts | 4 +- .erb/configs/webpack.config.renderer.prod.ts | 8 +- .github/workflows/publish.yml | 144 +++++++++++++++---- .github/workflows/sonar-analysis.yml | 2 +- .github/workflows/test.yml | 2 +- Dockerfile.release | 37 +++++ README.md | 22 +++ beforeBuild.js | 10 ++ env.d.ts | 13 +- package.json | 13 +- packages/fuse-daemon/Makefile | 5 +- 12 files changed, 220 insertions(+), 55 deletions(-) create mode 100644 Dockerfile.release diff --git a/.env.example b/.env.example index bce9b2abcd..76a03a7fad 100644 --- a/.env.example +++ b/.env.example @@ -1,19 +1,14 @@ +# Encryption keys used during build CRYPTO_KEY= MAGIC_IV= MAGIC_SALT= NEW_CRYPTO_KEY= +# Core API endpoints NEW_DRIVE_URL= -DRIVE_API_URL= -PAYMENTS_URL= -INTERNXT_DESKTOP_HEADER_KEY= - BRIDGE_URL= -APP_SEGMENT_KEY= -APP_SEGMENT_KEY_TEST= -BUG_REPORTING_URL= +PAYMENTS_URL= NOTIFICATIONS_URL= -LOCK_REFRESH_INTERVAL= -RUDDERSTACK_KEY= -RUDDERSTACK_DATA_PLANE_URL= +# Desktop client identification +INTERNXT_DESKTOP_HEADER_KEY= diff --git a/.erb/configs/webpack.config.main.prod.ts b/.erb/configs/webpack.config.main.prod.ts index 4bc5aa287f..c6d1a82d92 100644 --- a/.erb/configs/webpack.config.main.prod.ts +++ b/.erb/configs/webpack.config.main.prod.ts @@ -38,11 +38,13 @@ const configuration: webpack.Configuration = { }, optimization: { + chunkIds: 'deterministic', minimizer: [ new TerserPlugin({ - parallel: true, + parallel: false, }), ], + moduleIds: 'deterministic', }, plugins: [ diff --git a/.erb/configs/webpack.config.renderer.prod.ts b/.erb/configs/webpack.config.renderer.prod.ts index 3a4189b3ff..5679b558ff 100644 --- a/.erb/configs/webpack.config.renderer.prod.ts +++ b/.erb/configs/webpack.config.renderer.prod.ts @@ -94,13 +94,17 @@ const configuration: webpack.Configuration = { }, optimization: { + chunkIds: 'deterministic', minimize: true, minimizer: [ new TerserPlugin({ - parallel: true, + parallel: false, + }), + new CssMinimizerPlugin({ + parallel: false, }), - new CssMinimizerPlugin(), ], + moduleIds: 'deterministic', }, plugins: [ diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 27d15fc8b8..ee21a61205 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,30 +4,24 @@ on: release: types: [published] workflow_dispatch: + inputs: + publish_to_github: + description: "Publish artifacts to GitHub release" + required: true + default: "false" + type: choice + options: + - "false" + - "true" jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 permissions: - contents: read + contents: write id-token: write - packages: write steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version-file: '.nvmrc' - - - name: Create .npmrc file - run: | - echo "@internxt:registry=https://npm.pkg.github.com/" > .npmrc - echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc - - - name: Install rpm build tools - run: sudo apt-get install -y rpm - - - name: Install dependencies - run: npm ci - name: Add .env run: | @@ -37,18 +31,116 @@ jobs: echo "MAGIC_SALT=${{ secrets.MAGIC_SALT }}" >> .env echo "NEW_CRYPTO_KEY=${{ secrets.NEW_CRYPTO_KEY }}" >> .env echo "NEW_DRIVE_URL=https://gateway.internxt.com/drive" >> .env - echo "DRIVE_API_URL=https://gateway.internxt.com/api" >> .env echo "PAYMENTS_URL=https://gateway.internxt.com/payments" >> .env echo "INTERNXT_DESKTOP_HEADER_KEY=${{ secrets.INTERNXT_DESKTOP_HEADER_KEY }}" >> .env echo "BRIDGE_URL=https://gateway.internxt.com/network" >> .env - echo "APP_SEGMENT_KEY=${{ secrets.APP_SEGMENT_KEY }}" >> .env - echo "APP_SEGMENT_KEY_TEST=${{ secrets.APP_SEGMENT_KEY_TEST }}" >> .env - echo "BUG_REPORTING_URL=https://desktop-bug-reporting.inxt.workers.dev" >> .env echo "NOTIFICATIONS_URL=https://notifications.internxt.com" >> .env - echo "LOCK_REFRESH_INTERVAL=20000" >> .env - - name: Build app - run: npm run build + - name: Build release container image + run: docker build -f Dockerfile.release -t internxt-release-builder:24.04 . + + - name: Build app inside container + env: + PUBLISH_TO_GITHUB: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_github == 'true') }} + run: | + docker run --rm \ + -e CI=true \ + -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ + -e PUBLISH_TO_GITHUB=${PUBLISH_TO_GITHUB} \ + -v "$PWD:/workspace" \ + -w /workspace \ + internxt-release-builder:24.04 \ + bash -lc ' + set -euo pipefail + npm ci + node <<"EOF" > build-manifest.json + const packageJson = require("./package.json"); + const { execSync } = require("child_process"); + + function run(command) { + return execSync(command, { encoding: "utf8" }).trim(); + } + + const manifest = { + platform: process.platform, + arch: process.arch, + node: process.version, + npm: run("npm --version"), + go: run("go version"), + image: "internxt-release-builder:24.04", + electron: packageJson.devDependencies.electron, + electronBuilder: packageJson.devDependencies["electron-builder"], + electronRebuild: packageJson.devDependencies["@electron/rebuild"], + betterSqlite3: packageJson.dependencies["better-sqlite3"], + }; + + process.stdout.write(JSON.stringify(manifest, null, 2)); + EOF + dpkg-query -W \ + build-essential \ + ca-certificates \ + curl \ + make \ + pkg-config \ + python3 \ + rpm > system-packages.txt + + if [[ "${PUBLISH_TO_GITHUB}" == "true" ]]; then + npm run publish + else + npm run package + fi + + find build -maxdepth 1 -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.yml" \) -print0 \ + | sort -z \ + | xargs -0 sha256sum > build-checksums.txt + ' - - name: Publish app - run: npm run publish + - name: Upload release artifacts + if: success() + uses: actions/upload-artifact@v4 + with: + name: linux-release-artifacts + path: | + build/*.AppImage + build/*.deb + build/*.rpm + build/*.yml + + - name: Upload build metadata + if: always() + uses: actions/upload-artifact@v4 + with: + name: build-metadata + path: | + build-manifest.json + build-checksums.txt + system-packages.txt + + smoke-test-deb: + needs: build + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, ubuntu-latest] + steps: + - name: Download release artifacts + uses: actions/download-artifact@v4 + with: + name: linux-release-artifacts + path: build + + - name: Install runtime dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends xvfb + + - name: Install deb package for smoke test + run: | + sudo dpkg -i --force-depends build/*.deb + test -x /opt/Internxt/internxt + + - name: Start app in headless mode + run: | + xvfb-run -a /opt/Internxt/internxt --no-sandbox --version diff --git a/.github/workflows/sonar-analysis.yml b/.github/workflows/sonar-analysis.yml index 0c90ebb024..c0e66cfb78 100644 --- a/.github/workflows/sonar-analysis.yml +++ b/.github/workflows/sonar-analysis.yml @@ -22,7 +22,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y libfuse2 libgtk-3-0 libnotify4 libnss3 libxss1 libxtst6 xdg-utils libatspi2.0-0 libdrm2 libgbm1 libasound2t64 + sudo apt-get install -y libgtk-3-0 libnotify4 libnss3 libxss1 libxtst6 xdg-utils libatspi2.0-0 libdrm2 libgbm1 libasound2t64 - name: Install dependencies run: npm ci --ignore-scripts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f84186aad6..46b7b28db3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y libfuse2 libgtk-3-0 libnotify4 libnss3 libxss1 libxtst6 xdg-utils libatspi2.0-0 libdrm2 libgbm1 libasound2t64 + sudo apt-get install -y libgtk-3-0 libnotify4 libnss3 libxss1 libxtst6 xdg-utils libatspi2.0-0 libdrm2 libgbm1 libasound2t64 - name: Install dependencies run: npm ci --ignore-scripts diff --git a/Dockerfile.release b/Dockerfile.release new file mode 100644 index 0000000000..8ad58a1821 --- /dev/null +++ b/Dockerfile.release @@ -0,0 +1,37 @@ +FROM ubuntu:24.04 + +ARG DEBIAN_FRONTEND=noninteractive +ARG NODE_VERSION=20.20.2 +ARG GO_VERSION=1.26.1 + +ENV LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + NODE_ENV=production + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + build-essential \ + git \ + make \ + pkg-config \ + python3 \ + rpm \ + xz-utils \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz" -o /tmp/node.tar.xz \ + && mkdir -p /usr/local/node \ + && tar -xJf /tmp/node.tar.xz -C /usr/local/node --strip-components=1 \ + && ln -s /usr/local/node/bin/node /usr/local/bin/node \ + && ln -s /usr/local/node/bin/npm /usr/local/bin/npm \ + && ln -s /usr/local/node/bin/npx /usr/local/bin/npx \ + && rm /tmp/node.tar.xz + +RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tar.gz \ + && rm -rf /usr/local/go \ + && tar -C /usr/local -xzf /tmp/go.tar.gz \ + && ln -s /usr/local/go/bin/go /usr/local/bin/go \ + && rm /tmp/go.tar.gz + +WORKDIR /workspace \ No newline at end of file diff --git a/README.md b/README.md index e85e662a24..ac8a2c0258 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,28 @@ Building the `.rpm` package requires `rpmbuild`. On Ubuntu or Debian, install th sudo apt-get install rpm ``` +### Official Release Build (CI Container) + +The official release pipeline builds and publishes artifacts inside a pinned container image (`Dockerfile.release`) to reduce host drift. + +Current release flow: + +1. Build container image from `ubuntu:24.04`. +2. Run `npm ci` and `npm run publish` inside the container. +3. Upload generated artifacts (`.deb`, `.rpm`, `.AppImage`) plus build metadata. +4. Run smoke tests on the generated `.deb` without rebuilding it. + +### Smoke Test Strategy + +The release workflow includes a smoke test job that: + +1. Downloads the previously built `.deb` artifact. +2. Installs runtime dependencies for Linux GUI startup checks. +3. Installs the package and verifies `/opt/Internxt/internxt` exists. +4. Launches the binary in headless mode (`xvfb-run`) and checks startup. + +This validates the `build once, validate many` approach by reusing the same artifact produced in the release step. + ## Login Configuration Using Deeplink Create a script in the root of the project named `enable-sso.sh` and add the following content: diff --git a/beforeBuild.js b/beforeBuild.js index 21d33affa7..27a1dcdab4 100644 --- a/beforeBuild.js +++ b/beforeBuild.js @@ -7,6 +7,16 @@ module.exports = async (context) => { // this, prebuild-install downloads an Electron-v116 prebuilt compiled for // Electron 24 (V8 11.0) which segfaults under Electron 25+ (V8 11.4). process.env.npm_config_build_from_source = 'true'; + console.log( + JSON.stringify({ + tag: 'ELECTRON_REBUILD', + appDir, + arch, + electronVersion, + nodeVersion: process.version, + buildFromSource: process.env.npm_config_build_from_source, + }), + ); await electronRebuild.rebuild({ buildPath: appDir, electronVersion, arch, force: true }); return false; diff --git a/env.d.ts b/env.d.ts index 10dca8a3fc..f23e5c4be1 100644 --- a/env.d.ts +++ b/env.d.ts @@ -1,20 +1,21 @@ declare global { namespace NodeJS { interface ProcessEnv { + // Encryption keys for backups and data protection CRYPTO_KEY: string; MAGIC_IV: string; MAGIC_SALT: string; NEW_CRYPTO_KEY: string; + + // Core API endpoints NEW_DRIVE_URL: string; BRIDGE_URL: string; - APP_SEGMENT_KEY: string; - APP_SEGMENT_KEY_TEST: string; - BUG_REPORTING_URL: string; - platform: string; + PAYMENTS_URL: string; NOTIFICATIONS_URL: string; - LOCK_REFRESH_INTERVAL: string; - DRIVE_API_URL: string; + INTERNXT_DESKTOP_HEADER_KEY: string; ENABLE_ANTIVIRUS?: string; + NODE_ENV?: string; + PORT?: string; } } } diff --git a/package.json b/package.json index 9597c53787..361089c343 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "scripts": { "build": "concurrently \"npm run build:main\" \"npm run build:renderer\" \"npm run build:daemon\"", - "build:daemon": "cd packages/fuse-daemon && go build -ldflags='-s -w' -o ../../dist/fuse-daemon ./cmd/daemon", + "build:daemon": "make -C packages/fuse-daemon build", "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts", "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts", "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir .", @@ -74,7 +74,6 @@ }, "deb": { "depends": [ - "libfuse2", "python3-nautilus" ] }, @@ -98,7 +97,7 @@ } }, "devDependencies": { - "@electron/rebuild": "^3.7.2", + "@electron/rebuild": "3.7.2", "@headlessui/react": "^1.4.2", "@iconscout/react-unicons": "^1.1.6", "@internxt/eslint-config-internxt": "^1.0.9", @@ -143,8 +142,8 @@ "detect-port": "^1.3.0", "dotenv": "^10.0.0", "dotenv-webpack": "^7.0.3", - "electron": "^29.0.0", - "electron-builder": "^23.6.0", + "electron": "29.0.0", + "electron-builder": "23.6.0", "electron-debug": "^3.2.0", "electron-fetch": "^1.9.1", "electron-store": "^8.0.1", @@ -206,7 +205,7 @@ "@internxt/sdk": "1.11.17", "async": "^3.2.4", "axios": "^1.1.3", - "better-sqlite3": "^11.10.0", + "better-sqlite3": "11.10.0", "bottleneck": "^2.19.5", "check-disk-space": "^3.4.0", "diod": "^2.0.0", @@ -225,4 +224,4 @@ "engines": { "node": ">=20.0.0 <21.0.0" } -} +} \ No newline at end of file diff --git a/packages/fuse-daemon/Makefile b/packages/fuse-daemon/Makefile index cd7e985560..a03dd61cbf 100644 --- a/packages/fuse-daemon/Makefile +++ b/packages/fuse-daemon/Makefile @@ -1,7 +1,10 @@ .PHONY: build test lint +GOFLAGS ?= -mod=readonly -trimpath -buildvcs=false +LDFLAGS ?= -s -w + build: - go build -ldflags="-s -w" -o ../../dist/fuse-daemon ./cmd/daemon + go build $(GOFLAGS) -ldflags="$(LDFLAGS)" -o ../../dist/fuse-daemon ./cmd/daemon test: go test ./... From a0bab1efa33891ad6c365ca352555f53911cf6a1 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Thu, 14 May 2026 15:20:12 -0500 Subject: [PATCH 02/14] fix: include dev dependencies in npm install for build process --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ee21a61205..59fd4638d1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -52,7 +52,7 @@ jobs: internxt-release-builder:24.04 \ bash -lc ' set -euo pipefail - npm ci + npm ci --include=dev node <<"EOF" > build-manifest.json const packageJson = require("./package.json"); const { execSync } = require("child_process"); From e6fbb71b866911cb56a08d3cccce53aaf2a9e9e5 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Thu, 14 May 2026 15:28:16 -0500 Subject: [PATCH 03/14] fix: streamline manifest generation in build process --- .github/workflows/publish.yml | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 59fd4638d1..8a3a0c4132 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -53,29 +53,7 @@ jobs: bash -lc ' set -euo pipefail npm ci --include=dev - node <<"EOF" > build-manifest.json - const packageJson = require("./package.json"); - const { execSync } = require("child_process"); - - function run(command) { - return execSync(command, { encoding: "utf8" }).trim(); - } - - const manifest = { - platform: process.platform, - arch: process.arch, - node: process.version, - npm: run("npm --version"), - go: run("go version"), - image: "internxt-release-builder:24.04", - electron: packageJson.devDependencies.electron, - electronBuilder: packageJson.devDependencies["electron-builder"], - electronRebuild: packageJson.devDependencies["@electron/rebuild"], - betterSqlite3: packageJson.dependencies["better-sqlite3"], - }; - - process.stdout.write(JSON.stringify(manifest, null, 2)); - EOF + node -e "const packageJson = require(\"./package.json\"); const { execSync } = require(\"child_process\"); const run = (command) => execSync(command, { encoding: \"utf8\" }).trim(); const manifest = { platform: process.platform, arch: process.arch, node: process.version, npm: run(\"npm --version\"), go: run(\"go version\"), image: \"internxt-release-builder:24.04\", electron: packageJson.devDependencies.electron, electronBuilder: packageJson.devDependencies[\"electron-builder\"], electronRebuild: packageJson.devDependencies[\"@electron/rebuild\"], betterSqlite3: packageJson.dependencies[\"better-sqlite3\"] }; process.stdout.write(JSON.stringify(manifest, null, 2));" > build-manifest.json dpkg-query -W \ build-essential \ ca-certificates \ From d4ace07c481ac741dd86de59e57641087b658a71 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Thu, 14 May 2026 16:08:56 -0500 Subject: [PATCH 04/14] fix: add initialization delay for headless app startup in smoke test --- .github/workflows/publish.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8a3a0c4132..307a2a3558 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -121,4 +121,7 @@ jobs: - name: Start app in headless mode run: | - xvfb-run -a /opt/Internxt/internxt --no-sandbox --version + xvfb-run -a /opt/Internxt/internxt --no-sandbox --version & + APP_PID=$! + sleep 5 # Allow app to initialize + kill $APP_PID From ee356ab9c1656a48f78c144fa0894abade08311b Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Fri, 15 May 2026 12:47:15 -0500 Subject: [PATCH 05/14] fix: refactor build process and add script for release build in container --- .github/workflows/publish.yml | 56 ++++++++++------------- scripts/run-release-build-in-container.sh | 13 ++++++ 2 files changed, 37 insertions(+), 32 deletions(-) create mode 100755 scripts/run-release-build-in-container.sh diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 307a2a3558..18b63c6ee4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,9 +17,6 @@ on: jobs: build: runs-on: ubuntu-24.04 - permissions: - contents: write - id-token: write steps: - uses: actions/checkout@v4 @@ -40,41 +37,15 @@ jobs: run: docker build -f Dockerfile.release -t internxt-release-builder:24.04 . - name: Build app inside container - env: - PUBLISH_TO_GITHUB: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_github == 'true') }} run: | docker run --rm \ -e CI=true \ - -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ - -e PUBLISH_TO_GITHUB=${PUBLISH_TO_GITHUB} \ -v "$PWD:/workspace" \ -w /workspace \ internxt-release-builder:24.04 \ - bash -lc ' - set -euo pipefail - npm ci --include=dev - node -e "const packageJson = require(\"./package.json\"); const { execSync } = require(\"child_process\"); const run = (command) => execSync(command, { encoding: \"utf8\" }).trim(); const manifest = { platform: process.platform, arch: process.arch, node: process.version, npm: run(\"npm --version\"), go: run(\"go version\"), image: \"internxt-release-builder:24.04\", electron: packageJson.devDependencies.electron, electronBuilder: packageJson.devDependencies[\"electron-builder\"], electronRebuild: packageJson.devDependencies[\"@electron/rebuild\"], betterSqlite3: packageJson.dependencies[\"better-sqlite3\"] }; process.stdout.write(JSON.stringify(manifest, null, 2));" > build-manifest.json - dpkg-query -W \ - build-essential \ - ca-certificates \ - curl \ - make \ - pkg-config \ - python3 \ - rpm > system-packages.txt - - if [[ "${PUBLISH_TO_GITHUB}" == "true" ]]; then - npm run publish - else - npm run package - fi + bash -lc './scripts/run-release-build-in-container.sh' - find build -maxdepth 1 -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.yml" \) -print0 \ - | sort -z \ - | xargs -0 sha256sum > build-checksums.txt - ' - - - name: Upload release artifacts + - name: Upload artifacts for smoke tests if: success() uses: actions/upload-artifact@v4 with: @@ -93,7 +64,6 @@ jobs: path: | build-manifest.json build-checksums.txt - system-packages.txt smoke-test-deb: needs: build @@ -125,3 +95,25 @@ jobs: APP_PID=$! sleep 5 # Allow app to initialize kill $APP_PID + + publish-release: + needs: smoke-test-deb + if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_github == 'true' && startsWith(github.ref, 'refs/tags/')) }} + runs-on: ubuntu-24.04 + permissions: + contents: write + steps: + - name: Download tested artifacts + uses: actions/download-artifact@v4 + with: + name: linux-release-artifacts + path: build + + - name: Publish tested artifacts to GitHub release + uses: softprops/action-gh-release@v2 + with: + files: | + build/*.AppImage + build/*.deb + build/*.rpm + build/*.yml diff --git a/scripts/run-release-build-in-container.sh b/scripts/run-release-build-in-container.sh new file mode 100755 index 0000000000..f77f938924 --- /dev/null +++ b/scripts/run-release-build-in-container.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail + +npm ci --include=dev + +node -e 'const packageJson = require("./package.json"); const { execSync } = require("child_process"); const run = (command) => execSync(command, { encoding: "utf8" }).trim(); const manifest = { platform: process.platform, arch: process.arch, node: process.version, npm: run("npm --version"), go: run("go version"), image: "internxt-release-builder:24.04", electron: packageJson.devDependencies.electron, electronBuilder: packageJson.devDependencies["electron-builder"], electronRebuild: packageJson.devDependencies["@electron/rebuild"], betterSqlite3: packageJson.dependencies["better-sqlite3"] }; process.stdout.write(JSON.stringify(manifest, null, 2));' > build-manifest.json + +npm run package + +find build -maxdepth 1 -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.yml" \) -print0 \ + | sort -z \ + | xargs -0 sha256sum > build-checksums.txt From 28e3f6431c5d3cab583d2735f0f59c1bf7e22f3e Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 08:57:39 -0500 Subject: [PATCH 06/14] fix: remove redundant validation note from release workflow section in README --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index ac8a2c0258..31d100e8db 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,6 @@ The release workflow includes a smoke test job that: 3. Installs the package and verifies `/opt/Internxt/internxt` exists. 4. Launches the binary in headless mode (`xvfb-run`) and checks startup. -This validates the `build once, validate many` approach by reusing the same artifact produced in the release step. - ## Login Configuration Using Deeplink Create a script in the root of the project named `enable-sso.sh` and add the following content: From f0472b9d6aa458b9c1bb375bfef6d471e2cbae05 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 12:10:27 -0500 Subject: [PATCH 07/14] fix: add GITHUB_TOKEN environment variable for artifact publishing --- .github/workflows/publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 18b63c6ee4..a5d1e13d0d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -111,6 +111,8 @@ jobs: - name: Publish tested artifacts to GitHub release uses: softprops/action-gh-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: | build/*.AppImage From 78ec5b3d0813301094a4c2b10d683a280ede2c86 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 12:13:15 -0500 Subject: [PATCH 08/14] fix: rename GITHUB_TOKEN to GH_TOKEN in publish workflow --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a5d1e13d0d..9be9d0653c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -112,7 +112,7 @@ jobs: - name: Publish tested artifacts to GitHub release uses: softprops/action-gh-release@v2 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: | build/*.AppImage From d2a8aa5dc8d403b9e7b20d801517c688f1afbea0 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 13:27:36 -0500 Subject: [PATCH 09/14] fix: add GH_TOKEN and GITHUB_TOKEN environment variables for Docker and release steps --- .github/workflows/publish.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9be9d0653c..0daba5b7a0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,6 +40,8 @@ jobs: run: | docker run --rm \ -e CI=true \ + -e GH_TOKEN=${{ secrets.GITHUB_TOKEN }} \ + -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ -v "$PWD:/workspace" \ -w /workspace \ internxt-release-builder:24.04 \ @@ -113,6 +115,7 @@ jobs: uses: softprops/action-gh-release@v2 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: | build/*.AppImage From cfaf77c47bc3ece135c7879b68898663a40ddeac Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 14:19:26 -0500 Subject: [PATCH 10/14] fix: update token usage in publish workflow to use github.token --- .github/workflows/publish.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0daba5b7a0..4a426bac84 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,8 +40,8 @@ jobs: run: | docker run --rm \ -e CI=true \ - -e GH_TOKEN=${{ secrets.GITHUB_TOKEN }} \ - -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ + -e GH_TOKEN=${{ github.token }} \ + -e GITHUB_TOKEN=${{ github.token }} \ -v "$PWD:/workspace" \ -w /workspace \ internxt-release-builder:24.04 \ @@ -114,8 +114,8 @@ jobs: - name: Publish tested artifacts to GitHub release uses: softprops/action-gh-release@v2 env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ github.token }} with: files: | build/*.AppImage From c691af563216c13cd57702e7c5d8a81e1e2e9be8 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 14:52:22 -0500 Subject: [PATCH 11/14] fix: ensure GH_TOKEN is set for GitHub publisher flows in build container --- scripts/run-release-build-in-container.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/run-release-build-in-container.sh b/scripts/run-release-build-in-container.sh index f77f938924..c8cfc7d0c7 100755 --- a/scripts/run-release-build-in-container.sh +++ b/scripts/run-release-build-in-container.sh @@ -2,6 +2,14 @@ set -euo pipefail +# electron-builder expects GH_TOKEN for GitHub publisher flows. +export GH_TOKEN="${GH_TOKEN:-${GITHUB_TOKEN:-}}" + +if [[ -z "${GH_TOKEN}" ]]; then + echo "GH_TOKEN/GITHUB_TOKEN is empty inside build container" + exit 1 +fi + npm ci --include=dev node -e 'const packageJson = require("./package.json"); const { execSync } = require("child_process"); const run = (command) => execSync(command, { encoding: "utf8" }).trim(); const manifest = { platform: process.platform, arch: process.arch, node: process.version, npm: run("npm --version"), go: run("go version"), image: "internxt-release-builder:24.04", electron: packageJson.devDependencies.electron, electronBuilder: packageJson.devDependencies["electron-builder"], electronRebuild: packageJson.devDependencies["@electron/rebuild"], betterSqlite3: packageJson.dependencies["better-sqlite3"] }; process.stdout.write(JSON.stringify(manifest, null, 2));' > build-manifest.json From c09f41418f7de06cb4f002cb6efe62c9a933d95f Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 15:16:09 -0500 Subject: [PATCH 12/14] fix: add validation for GH_TOKEN in build workflow --- .github/workflows/publish.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4a426bac84..2589b2fac7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,11 +37,19 @@ jobs: run: docker build -f Dockerfile.release -t internxt-release-builder:24.04 . - name: Build app inside container + env: + GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ github.token }} run: | + if [[ -z "${GH_TOKEN}" ]]; then + echo "GH_TOKEN is empty in workflow context" + exit 1 + fi + docker run --rm \ -e CI=true \ - -e GH_TOKEN=${{ github.token }} \ - -e GITHUB_TOKEN=${{ github.token }} \ + -e GH_TOKEN \ + -e GITHUB_TOKEN \ -v "$PWD:/workspace" \ -w /workspace \ internxt-release-builder:24.04 \ From a8877aa9c85d17063da25c1e3f3db2e6246cff3c Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 15:31:40 -0500 Subject: [PATCH 13/14] fix: streamline token handling in publish workflow and add validation for GH_TOKEN --- .github/workflows/publish.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2589b2fac7..cbf330a21a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,6 +17,9 @@ on: jobs: build: runs-on: ubuntu-24.04 + env: + GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@v4 @@ -37,9 +40,6 @@ jobs: run: docker build -f Dockerfile.release -t internxt-release-builder:24.04 . - name: Build app inside container - env: - GH_TOKEN: ${{ github.token }} - GITHUB_TOKEN: ${{ github.token }} run: | if [[ -z "${GH_TOKEN}" ]]; then echo "GH_TOKEN is empty in workflow context" @@ -110,9 +110,19 @@ jobs: needs: smoke-test-deb if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_github == 'true' && startsWith(github.ref, 'refs/tags/')) }} runs-on: ubuntu-24.04 + env: + GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ github.token }} permissions: contents: write steps: + - name: Validate GitHub token availability + run: | + if [[ -z "${GH_TOKEN}" ]]; then + echo "GH_TOKEN is empty in publish-release context" + exit 1 + fi + - name: Download tested artifacts uses: actions/download-artifact@v4 with: @@ -121,9 +131,6 @@ jobs: - name: Publish tested artifacts to GitHub release uses: softprops/action-gh-release@v2 - env: - GH_TOKEN: ${{ github.token }} - GITHUB_TOKEN: ${{ github.token }} with: files: | build/*.AppImage From aad1ca1ce785bf2d481ad22503f75234b01ce2a1 Mon Sep 17 00:00:00 2001 From: Esteban Galvis Date: Tue, 19 May 2026 15:49:28 -0500 Subject: [PATCH 14/14] fix: remove unnecessary publish configuration from package.json --- package.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index 361089c343..6a1e569745 100644 --- a/package.json +++ b/package.json @@ -91,10 +91,7 @@ "./clamAV/**", "./src/apps/nautilus-extension/internxt-virtual-drive.py", "./dist/fuse-daemon" - ], - "publish": { - "provider": "github" - } + ] }, "devDependencies": { "@electron/rebuild": "3.7.2",