mirror of
https://github.com/travelerdev/frameloader.git
synced 2026-10-17 15:01:32 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0693668b08 | ||
|
|
26872c7396 | ||
|
|
c6f1c8b203 |
No files matched your search
@@ -1,12 +1,13 @@
|
||||
name: Build
|
||||
|
||||
# Every push and pull request: check the code, then build installers for each
|
||||
# Every push to main and every pull request: check the code, then build installers for each
|
||||
# platform and attach them to the run as artifacts. The release workflow calls
|
||||
# this same file with a version to stamp into the app.
|
||||
on:
|
||||
# Pushes to main, plus pull requests. Branch pushes aren't built separately, so a
|
||||
# pull request's commits run once (as pull_request), not twice.
|
||||
push:
|
||||
branches: ["**"]
|
||||
tags-ignore: ["**"]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_call:
|
||||
inputs:
|
||||
@@ -18,6 +19,10 @@ on:
|
||||
description: Commit to build.
|
||||
type: string
|
||||
default: ""
|
||||
sign_mac:
|
||||
description: Sign and notarize the macOS build (needs the release-signing environment).
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: build-${{ github.workflow }}-${{ inputs.ref || github.ref }}
|
||||
@@ -56,9 +61,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: macOS
|
||||
os: macos-latest
|
||||
args: --mac --arm64 --x64
|
||||
- name: Windows
|
||||
os: windows-latest
|
||||
args: --win --x64
|
||||
@@ -98,7 +100,7 @@ jobs:
|
||||
CSC_IDENTITY_AUTO_DISCOVERY: "false"
|
||||
run: |
|
||||
pnpm build
|
||||
pnpm exec electron-builder ${{ matrix.args }} --publish never
|
||||
pnpm exec electron-builder --config electron-builder.config.cjs ${{ matrix.args }} --publish never
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frameloader-${{ matrix.os }}
|
||||
@@ -109,3 +111,71 @@ jobs:
|
||||
apps/desktop/release/*.AppImage
|
||||
apps/desktop/release/*.deb
|
||||
if-no-files-found: error
|
||||
|
||||
# macOS is its own job so release builds can run inside the protected
|
||||
# release-signing environment (approval required, v* tags only), which holds
|
||||
# the Developer ID certificate and the notarization key. Pushes and pull
|
||||
# requests never touch it and produce ad-hoc signed builds.
|
||||
package-mac:
|
||||
name: Package (macOS${{ inputs.sign_mac && ', signed' || '' }})
|
||||
needs: check
|
||||
runs-on: macos-latest
|
||||
environment: ${{ inputs.sign_mac && 'release-signing' || '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.ref || github.sha }}
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: pnpm
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- name: Stamp version
|
||||
if: inputs.version != ''
|
||||
run: node scripts/version.mjs set "${{ inputs.version }}"
|
||||
# Signing secrets live only in this step's environment, never in GITHUB_ENV, so no
|
||||
# later step or action (artifact upload, post steps) can read them. They're exported
|
||||
# only for signed builds: electron-builder treats an empty CSC_LINK as a file path.
|
||||
- name: Build installers
|
||||
working-directory: apps/desktop
|
||||
env:
|
||||
CSC_IDENTITY_AUTO_DISCOVERY: "false"
|
||||
SIGN_MAC: ${{ inputs.sign_mac }}
|
||||
SIGN_CSC_LINK: ${{ secrets.CSC_LINK }}
|
||||
SIGN_CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
||||
SIGN_APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
|
||||
SIGN_APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
|
||||
SIGN_APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
|
||||
run: |
|
||||
if [ "$SIGN_MAC" = "true" ]; then
|
||||
for name in SIGN_CSC_LINK SIGN_CSC_KEY_PASSWORD SIGN_APPLE_API_KEY SIGN_APPLE_API_KEY_ID SIGN_APPLE_API_ISSUER; do
|
||||
if [ -z "${!name}" ]; then
|
||||
echo "::error::release-signing secret ${name#SIGN_} is missing. See README → Signing."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
key_file="$RUNNER_TEMP/notary.p8"
|
||||
printf '%s' "$SIGN_APPLE_API_KEY" > "$key_file"
|
||||
trap 'rm -f "$key_file"' EXIT
|
||||
export CSC_LINK="$SIGN_CSC_LINK" CSC_KEY_PASSWORD="$SIGN_CSC_KEY_PASSWORD"
|
||||
export APPLE_API_KEY="$key_file" APPLE_API_KEY_ID="$SIGN_APPLE_API_KEY_ID" APPLE_API_ISSUER="$SIGN_APPLE_API_ISSUER"
|
||||
fi
|
||||
unset SIGN_CSC_LINK SIGN_CSC_KEY_PASSWORD SIGN_APPLE_API_KEY SIGN_APPLE_API_KEY_ID SIGN_APPLE_API_ISSUER
|
||||
pnpm build
|
||||
pnpm exec electron-builder --config electron-builder.config.cjs --mac --arm64 --x64 --publish never
|
||||
- name: Check signature
|
||||
if: inputs.sign_mac
|
||||
working-directory: apps/desktop
|
||||
run: |
|
||||
app="release/mac-arm64/Frameloader.app"
|
||||
codesign --verify --deep --strict --verbose=2 "$app"
|
||||
spctl --assess --type execute --verbose=2 "$app"
|
||||
xcrun stapler validate "$app"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frameloader-macos
|
||||
path: |
|
||||
apps/desktop/release/*.dmg
|
||||
apps/desktop/release/*.zip
|
||||
if-no-files-found: error
|
||||
@@ -37,9 +37,11 @@ jobs:
|
||||
name: Build
|
||||
needs: prepare
|
||||
uses: ./.github/workflows/build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
version: ${{ needs.prepare.outputs.version }}
|
||||
ref: refs/tags/${{ github.event.release.tag_name }}
|
||||
sign_mac: true
|
||||
|
||||
attach:
|
||||
name: Attach installers to the release
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<p align="center">
|
||||
<img src="apps/desktop/build/icon.png" alt="Frameloader logo" width="160" />
|
||||
</p>
|
||||
|
||||
# Frameloader
|
||||
|
||||
[www.frameloader.com](https://www.frameloader.com)
|
||||
@@ -64,7 +68,7 @@ Frameloader has no analytics, telemetry, crash reporting or accounts. It connect
|
||||
|
||||
## Builds and releases
|
||||
|
||||
Every push and pull request runs `.github/workflows/build.yml`: typecheck, tests, the website build, then installers for macOS (arm64 and x64), Windows x64, and Linux x64 and arm64. The installers are attached to the run as artifacts.
|
||||
Every push to `main` and every pull request runs `.github/workflows/build.yml`: typecheck, tests, the website build, then installers for macOS (arm64 and x64), Windows x64, and Linux x64 and arm64. The installers are attached to the run as artifacts.
|
||||
|
||||
To ship a release:
|
||||
|
||||
@@ -74,7 +78,7 @@ To ship a release:
|
||||
|
||||
Nothing is pushed to `main`, so this works with branch protection. The version in `apps/desktop/package.json` is only what local and CI builds report; releases take their version from the tag.
|
||||
|
||||
Builds are not code-signed yet. On macOS the app is ad-hoc signed, so the first launch needs right-click → Open (or `xattr -dr com.apple.quarantine /Applications/Frameloader.app`). Windows SmartScreen will warn until the installer is signed.
|
||||
**Signing.** Release builds of the Mac app are signed with a Developer ID certificate and notarized, so they open normally. The certificate and the App Store Connect notarization key live only in the `release-signing` GitHub environment as `CSC_LINK`, `CSC_KEY_PASSWORD`, `APPLE_API_KEY`, `APPLE_API_KEY_ID` and `APPLE_API_ISSUER`. That environment only accepts `v*` tags and needs approval, so the release run pauses until you approve it. Push and pull-request builds are ad-hoc signed; to open one on macOS 15 or later, use System Settings → Privacy & Security → Open Anyway, or run `xattr -dr com.apple.quarantine /Applications/Frameloader.app`. Windows builds are unsigned, so SmartScreen warns before the installer runs.
|
||||
|
||||
Installed apps notice new releases on their own: they check GitHub's releases API and show a banner with a link once a release has its installers attached. Nothing is downloaded or installed automatically, and Settings → Updates turns the check off.
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- V8's JIT needs these under the hardened runtime. -->
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 821 KiB |
@@ -0,0 +1,85 @@
|
||||
// electron-builder config. Pass with: electron-builder --config electron-builder.config.cjs
|
||||
//
|
||||
// macOS signing depends on the environment:
|
||||
// - Release builds (the release-signing GitHub environment) set CSC_LINK, so the app is
|
||||
// signed with the Developer ID certificate, uses the hardened runtime, and is notarized
|
||||
// with the App Store Connect key (APPLE_API_KEY / APPLE_API_KEY_ID / APPLE_API_ISSUER).
|
||||
// - Everything else (local builds, pushes, pull requests) is ad-hoc signed.
|
||||
const signed = Boolean(process.env.CSC_LINK);
|
||||
|
||||
const base = {
|
||||
"appId": "dev.traveler.frameloader",
|
||||
"productName": "Frameloader",
|
||||
"directories": {
|
||||
"output": "release",
|
||||
"buildResources": "build"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"package.json",
|
||||
"!dist/test/**",
|
||||
"!dist/**/*.map"
|
||||
],
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "vendor/devkit-utils",
|
||||
"to": "devkit-utils",
|
||||
"filter": [
|
||||
"**/*",
|
||||
"!**/__pycache__/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
"mac": {
|
||||
"category": "public.app-category.utilities",
|
||||
"target": [
|
||||
"dmg",
|
||||
"zip"
|
||||
],
|
||||
"artifactName": "Frameloader-mac-${arch}.${ext}",
|
||||
"extendInfo": {
|
||||
"NSLocalNetworkUsageDescription": "Frameloader connects to your Steam Frame on your local network to install and launch apps.",
|
||||
"NSBonjourServices": [
|
||||
"_steamos-devkit._tcp",
|
||||
"_ssh._tcp"
|
||||
]
|
||||
}
|
||||
},
|
||||
"win": {
|
||||
"target": [
|
||||
"nsis",
|
||||
"zip"
|
||||
],
|
||||
"artifactName": "Frameloader-win-${arch}.${ext}"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"perMachine": false,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
"AppImage",
|
||||
"deb"
|
||||
],
|
||||
"category": "Utility",
|
||||
"artifactName": "Frameloader-linux-${arch}.${ext}",
|
||||
"executableName": "frameloader"
|
||||
},
|
||||
"electronVersion": "44.5.1"
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
mac: {
|
||||
...base.mac,
|
||||
...(signed
|
||||
? {
|
||||
hardenedRuntime: true,
|
||||
entitlements: "build/entitlements.mac.plist",
|
||||
entitlementsInherit: "build/entitlements.mac.plist",
|
||||
notarize: true,
|
||||
}
|
||||
: { identity: "-", hardenedRuntime: false }),
|
||||
},
|
||||
};
|
||||
@@ -4,7 +4,10 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Drop an APK, Windows app, or Linux build onto your Steam Frame and it shows up in your Steam library.",
|
||||
"license": "MIT",
|
||||
"author": "Zack <zack@traveler.dev>",
|
||||
"author": {
|
||||
"name": "Traveler Dev Ltd",
|
||||
"email": "hi@traveler.dev"
|
||||
},
|
||||
"private": true,
|
||||
"main": "dist/main.cjs",
|
||||
"type": "module",
|
||||
@@ -14,10 +17,10 @@
|
||||
"start": "pnpm build && electron .",
|
||||
"typecheck": "tsc -p tsconfig.main.json --noEmit && tsc -p tsconfig.renderer.json --noEmit",
|
||||
"test": "pnpm build && node --test dist/test/*.test.cjs",
|
||||
"dist": "pnpm build && electron-builder --publish never",
|
||||
"dist:mac": "pnpm build && electron-builder --mac --arm64 --publish never",
|
||||
"dist:win": "pnpm build && electron-builder --win --x64 --publish never",
|
||||
"dist:linux": "pnpm build && electron-builder --linux --x64 --arm64 --publish never",
|
||||
"dist": "pnpm build && electron-builder --config electron-builder.config.cjs --publish never",
|
||||
"dist:mac": "pnpm build && electron-builder --config electron-builder.config.cjs --mac --arm64 --publish never",
|
||||
"dist:win": "pnpm build && electron-builder --config electron-builder.config.cjs --win --x64 --publish never",
|
||||
"dist:linux": "pnpm build && electron-builder --config electron-builder.config.cjs --linux --x64 --arm64 --publish never",
|
||||
"screenshots": "pnpm build && electron scripts/screenshot.cjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -35,62 +38,6 @@
|
||||
"typescript": "^7.0.2",
|
||||
"yauzl": "^3.2.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "dev.traveler.frameloader",
|
||||
"productName": "Frameloader",
|
||||
"directories": {
|
||||
"output": "release",
|
||||
"buildResources": "build"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"package.json",
|
||||
"!dist/test/**",
|
||||
"!dist/**/*.map"
|
||||
],
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "vendor/devkit-utils",
|
||||
"to": "devkit-utils",
|
||||
"filter": [
|
||||
"**/*",
|
||||
"!**/__pycache__/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
"mac": {
|
||||
"category": "public.app-category.utilities",
|
||||
"target": [
|
||||
"dmg",
|
||||
"zip"
|
||||
],
|
||||
"artifactName": "Frameloader-mac-${arch}.${ext}",
|
||||
"identity": "-",
|
||||
"hardenedRuntime": false
|
||||
},
|
||||
"win": {
|
||||
"target": [
|
||||
"nsis",
|
||||
"zip"
|
||||
],
|
||||
"artifactName": "Frameloader-win-${arch}.${ext}"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"perMachine": false,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
"AppImage",
|
||||
"deb"
|
||||
],
|
||||
"category": "Utility",
|
||||
"artifactName": "Frameloader-linux-${arch}.${ext}",
|
||||
"executableName": "frameloader"
|
||||
},
|
||||
"electronVersion": "44.5.1"
|
||||
},
|
||||
"homepage": "https://www.frameloader.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"private": true,
|
||||
"description": "The Frameloader website.",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Traveler Dev Ltd",
|
||||
"email": "hi@traveler.dev"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
"name": "frameloader-monorepo",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Traveler Dev Ltd",
|
||||
"email": "hi@traveler.dev"
|
||||
},
|
||||
"packageManager": "pnpm@11.24.0",
|
||||
"scripts": {
|
||||
"build": "pnpm -r build",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"private": true,
|
||||
"description": "Shared color, type and shape tokens for the Frameloader app and website.",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Traveler Dev Ltd",
|
||||
"email": "hi@traveler.dev"
|
||||
},
|
||||
"exports": {
|
||||
"./tokens.css": "./tokens.css"
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user