Some checks are pending
Tests & Quality Checks / Test on Python 3.11 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.11-1 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12-1 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.10 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.11-2 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12-2 (push) Waiting to run
Tests & Quality Checks / Build Artifacts (push) Blocked by required conditions
Tests & Quality Checks / Build Artifacts-1 (push) Blocked by required conditions
488 lines
No EOL
14 KiB
Markdown
488 lines
No EOL
14 KiB
Markdown
# Branding, Builds, and Releases
|
|
|
|
This document describes how branded builds work in this repository, how to add or edit a brand, how to build the default and branded variants, and how to publish releases.
|
|
|
|
## Overview
|
|
|
|
The project supports one default product and any number of branded variants from the same codebase.
|
|
|
|
- The default product is defined by built-in defaults in `build/scripts/brand_config.py`.
|
|
- The default product identifier is `webdrop_bridge`.
|
|
- Additional brands are defined by JSON manifests in `build/brands/`.
|
|
- Runtime behavior can also be branded through application config values such as `brand_id`, `config_dir_name`, `app_name`, and update settings.
|
|
- Windows and macOS installers are built as separate artifacts per brand.
|
|
- Releases are shared by version. A single Forgejo release can contain installers for the default product and multiple brands.
|
|
|
|
## Branding Model
|
|
|
|
There are two layers to branding:
|
|
|
|
1. Packaging identity
|
|
Controls installer name, executable/app bundle name, product display name, bundle identifier, MSI upgrade code, installer artwork, and related metadata.
|
|
|
|
2. Runtime configuration
|
|
Controls app name shown in the UI, config directory name, update feed settings, URL mappings, allowed roots, and similar application behavior.
|
|
|
|
Packaging identity lives in `build/brands/<brand>.json`.
|
|
|
|
Runtime configuration lives in app config files loaded by the application. See `config.example.json` for the current branded example.
|
|
|
|
## Important Files
|
|
|
|
- `build/scripts/brand_config.py`: central helper for brand metadata, artifact naming, and release manifest generation
|
|
- `build/brands/agravity.json`: example branded manifest
|
|
- `build/scripts/build_windows.py`: Windows build entrypoint
|
|
- `build/scripts/build_macos.sh`: macOS build entrypoint
|
|
- `build/scripts/create_release.ps1`: Windows release uploader
|
|
- `build/scripts/create_release.sh`: macOS release uploader
|
|
- `config.example.json`: example runtime branding config
|
|
|
|
## Create a New Brand
|
|
|
|
To create a new brand, add a new manifest file under `build/brands/`.
|
|
|
|
Example:
|
|
|
|
1. Copy `build/brands/template.jsonc` to `build/brands/<new-brand>.json`.
|
|
2. Update the values for the new brand.
|
|
3. Add any brand-specific assets if you do not want to reuse the default icons/license assets.
|
|
|
|
Minimal example:
|
|
|
|
```json
|
|
{
|
|
"brand_id": "customerx",
|
|
"display_name": "Customer X Bridge",
|
|
"asset_prefix": "CustomerXBridge",
|
|
"exe_name": "CustomerXBridge",
|
|
"manufacturer": "Customer X",
|
|
"install_dir_name": "Customer X Bridge",
|
|
"shortcut_description": "Customer X drag-and-drop bridge",
|
|
"bundle_identifier": "com.customerx.bridge",
|
|
"config_dir_name": "customerx_bridge",
|
|
"msi_upgrade_code": "PUT-A-NEW-GUID-HERE",
|
|
"update_channel": "stable",
|
|
"icon_ico": "resources/icons/app.ico",
|
|
"icon_icns": "resources/icons/app.icns",
|
|
"dialog_bmp": "resources/icons/background.bmp",
|
|
"banner_bmp": "resources/icons/banner.bmp",
|
|
"license_rtf": "resources/license.rtf"
|
|
}
|
|
```
|
|
|
|
### Required Fields
|
|
|
|
- `brand_id`: internal identifier used for build output folders and release manifest entries
|
|
- `display_name`: user-facing product name
|
|
- `asset_prefix`: base name for installer artifacts and app bundle name
|
|
- `exe_name`: executable name for Windows and app bundle name base for macOS
|
|
- `manufacturer`: MSI manufacturer string
|
|
- `install_dir_name`: installation directory name shown to the OS
|
|
- `shortcut_description`: Windows shortcut description
|
|
- `bundle_identifier`: macOS bundle identifier
|
|
- `config_dir_name`: local app config/log/cache directory name
|
|
- `msi_upgrade_code`: stable GUID for Windows upgrades
|
|
- `update_channel`: currently typically `stable`
|
|
|
|
Generate a new `msi_upgrade_code` for a new brand once and keep it stable afterwards.
|
|
|
|
Examples:
|
|
|
|
```powershell
|
|
New-Guid
|
|
```
|
|
|
|
```bash
|
|
uuidgen
|
|
```
|
|
|
|
### Asset Fields
|
|
|
|
These can point at brand-specific files or default shared files:
|
|
|
|
- `icon_ico`
|
|
- `icon_icns`
|
|
- `dialog_bmp`
|
|
- `banner_bmp`
|
|
- `license_rtf`
|
|
|
|
Optional toolbar icon overrides:
|
|
|
|
- `toolbar_icon_home`
|
|
- `toolbar_icon_reload`
|
|
- `toolbar_icon_open`
|
|
- `toolbar_icon_openwith`
|
|
|
|
If a referenced asset path does not exist, the helper falls back to the default asset defined in `build/scripts/brand_config.py`.
|
|
|
|
For toolbar icons, the runtime looks for the configured paths in packaged and development layouts. If an icon is missing:
|
|
|
|
- Home falls back to a standard Qt home icon
|
|
- Reload/Open/OpenWith keep their existing icon behavior
|
|
|
|
### Identity Rules
|
|
|
|
Treat these values as long-lived product identity once a brand has shipped:
|
|
|
|
- `brand_id`
|
|
- `asset_prefix`
|
|
- `exe_name`
|
|
- `bundle_identifier`
|
|
- `config_dir_name`
|
|
- `msi_upgrade_code`
|
|
|
|
Changing them later can break one or more of the following:
|
|
|
|
- Windows upgrade behavior
|
|
- macOS app identity
|
|
- auto-update asset selection
|
|
- local config/log/cache continuity
|
|
- installer and artifact naming consistency
|
|
|
|
If the product is already in use, only change these values deliberately and with migration planning.
|
|
|
|
## Edit an Existing Brand
|
|
|
|
To edit a shipped or in-progress brand:
|
|
|
|
1. Update the brand manifest in `build/brands/<brand>.json`.
|
|
2. If needed, update brand-specific assets referenced by that manifest.
|
|
3. If runtime behavior should also change, update the relevant application config values.
|
|
4. Rebuild the affected platform artifacts.
|
|
5. Validate the result with a dry-run release before publishing.
|
|
|
|
Safe edits after release usually include:
|
|
|
|
- `display_name`
|
|
- `shortcut_description`
|
|
- artwork paths
|
|
- license text
|
|
- update channel, if release policy changes
|
|
|
|
High-risk edits after release are the identity fields listed above.
|
|
|
|
## Runtime Branding Configuration
|
|
|
|
Packaging branding alone is not enough if the app should also present a different name, use different local storage, or point to different update settings.
|
|
|
|
Relevant runtime config keys include:
|
|
|
|
- `brand_id`
|
|
- `config_dir_name`
|
|
- `app_name`
|
|
- `update_base_url`
|
|
- `update_repo`
|
|
- `update_channel`
|
|
- `update_manifest_name`
|
|
|
|
Toolbar icon env overrides (useful for packaged branding):
|
|
|
|
- `TOOLBAR_ICON_HOME`
|
|
- `TOOLBAR_ICON_RELOAD`
|
|
- `TOOLBAR_ICON_OPEN`
|
|
- `TOOLBAR_ICON_OPENWITH`
|
|
|
|
The current example in `config.example.json` shows the Agravity runtime setup.
|
|
|
|
When adding a new brand, make sure the runtime config matches the packaging manifest at least for:
|
|
|
|
- `brand_id`
|
|
- `config_dir_name`
|
|
- `app_name`
|
|
|
|
## Build the Default Product
|
|
|
|
### Windows
|
|
|
|
Build the default executable only:
|
|
|
|
```powershell
|
|
python .\build\scripts\build_windows.py
|
|
```
|
|
|
|
Build the default Windows MSI:
|
|
|
|
```powershell
|
|
python .\build\scripts\build_windows.py --msi
|
|
```
|
|
|
|
Build with a specific `.env` file:
|
|
|
|
```powershell
|
|
python .\build\scripts\build_windows.py --msi --env-file .\.env
|
|
```
|
|
|
|
### macOS
|
|
|
|
Build the default macOS app and DMG:
|
|
|
|
```bash
|
|
bash build/scripts/build_macos.sh
|
|
```
|
|
|
|
Build with a specific `.env` file:
|
|
|
|
```bash
|
|
bash build/scripts/build_macos.sh --env-file .env
|
|
```
|
|
|
|
## Build a Brand
|
|
|
|
### Windows
|
|
|
|
Build a branded executable only:
|
|
|
|
```powershell
|
|
python .\build\scripts\build_windows.py --brand agravity
|
|
```
|
|
|
|
Build a branded MSI:
|
|
|
|
```powershell
|
|
python .\build\scripts\build_windows.py --brand agravity --msi
|
|
```
|
|
|
|
### macOS
|
|
|
|
Build a branded macOS app and DMG:
|
|
|
|
```bash
|
|
bash build/scripts/build_macos.sh --brand agravity
|
|
```
|
|
|
|
## Build Output Locations
|
|
|
|
Windows artifacts are written to:
|
|
|
|
- `build/dist/windows/webdrop_bridge/` for the default product
|
|
- `build/dist/windows/<brand_id>/` for branded products
|
|
|
|
macOS artifacts are written to:
|
|
|
|
- `build/dist/macos/webdrop_bridge/` for the default product
|
|
- `build/dist/macos/<brand_id>/` for branded products
|
|
|
|
Typical artifact names:
|
|
|
|
- Windows MSI: `<asset_prefix>-<version>-win-x64.msi`
|
|
- Windows checksum: `<asset_prefix>-<version>-win-x64.msi.sha256`
|
|
- macOS DMG: `<asset_prefix>-<version>-macos-universal.dmg`
|
|
- macOS checksum: `<asset_prefix>-<version>-macos-universal.dmg.sha256`
|
|
|
|
## Create a Release
|
|
|
|
Releases are shared by version. The release scripts scan local build outputs on the current machine and upload every artifact they find for that platform.
|
|
|
|
This means:
|
|
|
|
- a Windows machine can upload all locally built MSIs for the current version
|
|
- a macOS machine can later upload all locally built DMGs for the same version
|
|
- both runs contribute to the same Forgejo release tag
|
|
- `release-manifest.json` is merged so later runs do not wipe earlier platform entries
|
|
|
|
### Windows Release
|
|
|
|
Dry run first:
|
|
|
|
```powershell
|
|
.\build\scripts\create_release.ps1 -DryRun
|
|
```
|
|
|
|
Publish all locally built Windows variants for the current version:
|
|
|
|
```powershell
|
|
.\build\scripts\create_release.ps1
|
|
```
|
|
|
|
Publish only selected brands:
|
|
|
|
```powershell
|
|
.\build\scripts\create_release.ps1 -Brands agravity
|
|
```
|
|
|
|
Publish only the default product:
|
|
|
|
```powershell
|
|
.\build\scripts\create_release.ps1 -Brands webdrop_bridge
|
|
```
|
|
|
|
Publish a specific version:
|
|
|
|
```powershell
|
|
.\build\scripts\create_release.ps1 -Version 0.8.4
|
|
```
|
|
|
|
### macOS Release
|
|
|
|
Dry run first:
|
|
|
|
```bash
|
|
bash build/scripts/create_release.sh --dry-run
|
|
```
|
|
|
|
Publish all locally built macOS variants for the current version:
|
|
|
|
```bash
|
|
bash build/scripts/create_release.sh
|
|
```
|
|
|
|
Publish only selected brands:
|
|
|
|
```bash
|
|
bash build/scripts/create_release.sh --brand agravity
|
|
```
|
|
|
|
Publish only the default product:
|
|
|
|
```bash
|
|
bash build/scripts/create_release.sh --brand webdrop_bridge
|
|
```
|
|
|
|
Publish a specific version:
|
|
|
|
```bash
|
|
bash build/scripts/create_release.sh --version 0.8.4
|
|
```
|
|
|
|
### Credentials
|
|
|
|
Both release scripts use Forgejo credentials from environment variables when available:
|
|
|
|
- `FORGEJO_USER`
|
|
- `FORGEJO_PASS`
|
|
|
|
If they are not set and you are not in dry-run mode, the script prompts for them.
|
|
|
|
Both scripts also support clearing credentials from the current shell session:
|
|
|
|
- Windows: `-ClearCredentials`
|
|
- macOS: `--clear-credentials`
|
|
|
|
## Dry Run Behavior
|
|
|
|
Dry-run mode is the preferred validation step before publishing.
|
|
|
|
Dry-run mode:
|
|
|
|
- discovers the local artifacts exactly like a real release run
|
|
- prints the release tag and target release URL
|
|
- prints the brands that were discovered locally
|
|
- prints the artifact paths that would be uploaded
|
|
- writes a local manifest preview to `build/dist/release-manifest.json`
|
|
- does not prompt for credentials
|
|
- does not perform network requests
|
|
- does not delete or upload assets
|
|
|
|
## Release Manifest
|
|
|
|
The release scripts generate and upload `release-manifest.json`.
|
|
|
|
This file is used by the updater to select the correct installer and checksum for a given brand and platform.
|
|
|
|
Current platform keys are:
|
|
|
|
- `windows-x64`
|
|
- `macos-universal`
|
|
|
|
The manifest is built from local artifacts and merged with any existing manifest already attached to the release.
|
|
|
|
## First Manual Download (Before Auto-Update)
|
|
|
|
After creating a release, a user can manually download the first installer directly from Forgejo. Once installed, auto-update handles later versions.
|
|
|
|
Base repository URL:
|
|
|
|
- `https://git.him-tools.de/HIM-public/webdrop-bridge`
|
|
|
|
Release page pattern:
|
|
|
|
- `https://git.him-tools.de/HIM-public/webdrop-bridge/releases/tag/v<version>`
|
|
|
|
Direct asset download pattern:
|
|
|
|
- `https://git.him-tools.de/HIM-public/webdrop-bridge/releases/download/v<version>/<asset-file-name>`
|
|
|
|
Example asset names:
|
|
|
|
- `WebDropBridge-0.8.4-win-x64.msi`
|
|
- `WebDropBridge-0.8.4-macos-universal.dmg`
|
|
- `AgravityBridge-0.8.4-win-x64.msi`
|
|
- `AgravityBridge-0.8.4-macos-universal.dmg`
|
|
|
|
### wget Examples
|
|
|
|
```bash
|
|
# Default Windows installer
|
|
wget "https://git.him-tools.de/HIM-public/webdrop-bridge/releases/download/v0.8.4/WebDropBridge-0.8.4-win-x64.msi"
|
|
|
|
# Agravity macOS installer
|
|
wget "https://git.him-tools.de/HIM-public/webdrop-bridge/releases/download/v0.8.4/AgravityBridge-0.8.4-macos-universal.dmg"
|
|
```
|
|
|
|
### curl Examples
|
|
|
|
```bash
|
|
# Default macOS installer
|
|
curl -L -o WebDropBridge-0.8.4-macos-universal.dmg \
|
|
"https://git.him-tools.de/HIM-public/webdrop-bridge/releases/download/v0.8.4/WebDropBridge-0.8.4-macos-universal.dmg"
|
|
|
|
# Agravity Windows installer
|
|
curl -L -o AgravityBridge-0.8.4-win-x64.msi \
|
|
"https://git.him-tools.de/HIM-public/webdrop-bridge/releases/download/v0.8.4/AgravityBridge-0.8.4-win-x64.msi"
|
|
```
|
|
|
|
### PowerShell Example
|
|
|
|
```powershell
|
|
Invoke-WebRequest `
|
|
-Uri "https://git.him-tools.de/HIM-public/webdrop-bridge/releases/download/v0.8.4/WebDropBridge-0.8.4-win-x64.msi" `
|
|
-OutFile "WebDropBridge-0.8.4-win-x64.msi"
|
|
```
|
|
|
|
You can inspect `release-manifest.json` on the release to see the exact file names for each brand and platform.
|
|
|
|
## Recommended Workflow for a New Brand
|
|
|
|
1. Create `build/brands/<brand>.json`.
|
|
2. Add or update brand-specific assets if needed.
|
|
3. Prepare matching runtime config values.
|
|
4. Build the brand on Windows and/or macOS.
|
|
5. Run the release script in dry-run mode.
|
|
6. Verify artifact names, discovered brands, and manifest contents.
|
|
7. Run the actual release script.
|
|
8. Validate update behavior against the shared release.
|
|
|
|
## Troubleshooting Notes
|
|
|
|
### Brand not discovered by release script
|
|
|
|
Check that:
|
|
|
|
- the build completed successfully
|
|
- the artifact is under the expected platform folder
|
|
- the artifact name matches the `asset_prefix` and current version
|
|
- the version used by the release script matches the built artifact version
|
|
|
|
### Windows upgrade behavior is wrong
|
|
|
|
Check that the brand has its own stable `msi_upgrade_code`. Reusing or changing it incorrectly will break expected MSI upgrade semantics.
|
|
|
|
### App uses the wrong local config folder
|
|
|
|
Check that runtime config uses the intended `config_dir_name`, and that it matches the packaging brand you expect.
|
|
|
|
### Auto-update downloads the wrong installer
|
|
|
|
Check that:
|
|
|
|
- the release contains the correct installer files
|
|
- `release-manifest.json` includes the correct brand and platform entry
|
|
- runtime update settings point to the expected repo/channel/manifest
|
|
|
|
## Current Example Brand
|
|
|
|
The first branded variant currently in the repository is:
|
|
|
|
- `build/brands/agravity.json`
|
|
|
|
Use it as the template for future branded variants. |