webdrop-bridge/docs/BRANDING_AND_RELEASES.md
claudi df76cb9b36
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
feat: Add toolbar icon configuration and update handling for Agravity
2026-03-12 09:07:14 +01:00

14 KiB

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:

{
  "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:

New-Guid
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:

python .\build\scripts\build_windows.py

Build the default Windows MSI:

python .\build\scripts\build_windows.py --msi

Build with a specific .env file:

python .\build\scripts\build_windows.py --msi --env-file .\.env

macOS

Build the default macOS app and DMG:

bash build/scripts/build_macos.sh

Build with a specific .env file:

bash build/scripts/build_macos.sh --env-file .env

Build a Brand

Windows

Build a branded executable only:

python .\build\scripts\build_windows.py --brand agravity

Build a branded MSI:

python .\build\scripts\build_windows.py --brand agravity --msi

macOS

Build a branded macOS app and DMG:

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:

.\build\scripts\create_release.ps1 -DryRun

Publish all locally built Windows variants for the current version:

.\build\scripts\create_release.ps1

Publish only selected brands:

.\build\scripts\create_release.ps1 -Brands agravity

Publish only the default product:

.\build\scripts\create_release.ps1 -Brands webdrop_bridge

Publish a specific version:

.\build\scripts\create_release.ps1 -Version 0.8.4

macOS Release

Dry run first:

bash build/scripts/create_release.sh --dry-run

Publish all locally built macOS variants for the current version:

bash build/scripts/create_release.sh

Publish only selected brands:

bash build/scripts/create_release.sh --brand agravity

Publish only the default product:

bash build/scripts/create_release.sh --brand webdrop_bridge

Publish a specific version:

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

# 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

# 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

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.

  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.