OpenTigDocs

Release automation

Builds and releases on GitHub

Next release draft runs on pushes to main, including direct commits and merged PRs, except changes confined to the public website. It creates one unpublished release draft on the first application change after a stable release and refreshes its notes on subsequent qualifying pushes. Automatic chore(release): prepare vX.Y.Z version commits and website-only commits are excluded from notes and do not start a new draft on their own; genuine maintenance and shared dependency updates remain included. Notes cover first-parent history since the highest published stable version, grouped into features, fixes, and maintenance, with commit links and verified PR links for GitHub merge/squash messages. Every entry credits its author with by @username: the PR creator for merged PRs, or the GitHub-linked commit author for direct commits. Unlinked commits show the author's recorded name without exposing their email. New Contributors lists each new human GitHub contributor once, linking their first included change; prior commit authors and merged-PR creators are recognized from the history of the previous stable tag, and bots are excluded from that section. Merge commits represent their PR once; rebased changes remain individual commits. Prereleases do not reset the stable changelog. Before the first release, the draft uses the package version and includes the eligible existing history.

The public website has a separate validation job within CI and is deployed manually to Cloudflare Workers. Website-only means every changed path is in website/ or docs/website.md; the former dedicated website workflow path is also recognized when filtering historical commits. Mixed commits and changes to shared manifests, lockfiles, or tooling remain application changes. Prepare release refuses to create a new application tag if only website changes have accumulated; the website is not versioned or published with the desktop and CLI.

The next version defaults to a patch increment (0.1.0 → 0.1.1). A higher version in package.json, or a higher version chosen on the managed draft, takes precedence without creating another draft. This proposal does not change package files or create a Git tag. You can edit the release title and add prose outside the opentig:release-notes comment markers; automatic refreshes preserve those edits and replace only the generated block. Drafting is independent of CI success and does not build installers or notify installed clients. It runs only on upstream main, uses the built-in Actions token, and needs no additional secret.

To prepare a release, open Actions → Prepare release → Run workflow, select main, and leave dry_run unchecked. It chooses the managed draft's proposed version (including a higher manually selected version), aligns the desktop/server package versions and workspace lockfile, and creates a version commit only when needed. The version commit and annotated vX.Y.Z tag are pushed together atomically; a concurrent push to main or branch protection rejection cannot leave a partial tag. The workflow then explicitly calls both the Windows and CLI builders, so the built-in Actions token is sufficient even though its pushes do not trigger another push workflow. No personal access token or manual tag creation is needed. The preparation job needs permission to push the version commit to main; it does not bypass branch protection.

Wait for the entire Prepare release run to succeed. The completed draft contains the Windows installer, .blockmap, latest.yml, opentig-cli-<version>.tgz, and opentig-headless.json with integrity hashes and the source tag/commit. Review notes and files, then click Publish release. This manual action makes the Windows update available and triggers Publish CLI to npm, which publishes the exact prepared tarball without rebuilding it. Wait for that workflow to succeed before installing the CLI from npm. Publishing a notes-only draft does not prepare its binaries. The optional dry_run checkbox previews the version without changing files, commits, tags or releases, and skips the builder.

Creating the tag freezes that release's code and notes. Commits arriving on main during the build stay out of the prepared version. If a run fails after creating the tag, run Prepare release again (or rerun the failed jobs): it resumes that exact tagged commit, even if main has advanced. Existing tags are never moved, and published releases are never overwritten. To include a code correction after a tag has been frozen, abandon that unpublished candidate explicitly and prepare a new version; rebuilding the same tag only retries infrastructure/build failures. The next push to main after publication starts the next draft and includes all changes since the published tag, including commits made while the prior release was being prepared. Next release draft can also be run manually on main to collect changes already there.

Portable Dev ZIPs for Windows and Linux are built only on demand. Open Actions → Desktop Dev builds → Run workflow and select the branch to evaluate. The workflow runs the quality gates on Linux and tests on Windows, builds both ZIPs, and verifies the packaged desktop/server plus the Windows utility and Trash integration. Run it when changing Electron, native dependencies, desktop packaging, installers, or updates, and before publishing a release. For a fork's branch, run it in the fork or check out the change on a branch in the main repository. PRs and pushes to main run the same automatic validation, system-trash checks, and packed CLI smoke tests without packaging the desktop application or checking its packaged server/utility integration. Download the OpenTig-Dev-<OS>-manual-<run> artifact from the manual workflow run, then extract the inner application ZIP completely. Artifacts expire after 14 days. These jobs have read-only repository permissions, no signing credentials, and no publishing step. A Dev build uses the same separate Dev profile as local builds. Linux jobs use ubuntu-24.04 explicitly so a change to GitHub's ubuntu-latest label does not migrate CI or release builders automatically.

Run Windows installer candidate manually in Actions to build an unsigned stable installer for evaluation. It runs the quality gates, package/runtime checks, and a disposable-runner install/uninstall test that checks installation registration and data preservation. Its artifact is kept for 14 days and has automatic updates disabled. Enable its release_mode option to additionally build and verify unsigned release metadata and an update-enabled installer without publishing anything. This does not constitute a successful upgrade test between two releases.

Windows release draft is called by Prepare release, and can also run for a stable vX.Y.Z tag or manually for an existing tag. The tag must match both package versions and point to a commit contained in main. It checks that commit, builds and verifies a Windows x64 installer and update metadata, tests installation/uninstallation on the runner, and uploads the installer, .blockmap, and latest.yml to a draft GitHub release. Within this builder, only the final draft-upload job has repository write permission; it never executes repository code or replaces an already published release. Publishing remains a deliberate release-page action after Windows validation.

CLI release draft builds from the same frozen tag as Windows, inspects the package, installs it globally on a disposable Linux runner, and checks startup, the web client, pairing, session persistence across restart, and graceful shutdown. It attaches the tarball and metadata only to the matching draft. Existing assets are never replaced; retries accept identical CLI assets. It can also run manually on main with an existing draft tag to complete an older release without changing its tag, notes, or Windows installer. A different existing CLI artifact is rejected instead of silently rebuilding an immutable version.

Configure npm Trusted publishing once in the settings for @opentig/cli: choose GitHub Actions, owner jorgefl8, repository opentig, workflow filename publish-cli.yml, and environment release. The publish job uses Node 24 and npm OIDC with provenance; no npm token is stored in GitHub or the application. The package must already exist and you must have permission to configure its publisher. Without this authorization, CLI publication fails even though the GitHub release and Windows update are available.

Publish CLI to npm accepts only a published stable release with matching tag, commit, package identity, and integrity. It never publishes a draft or prerelease. Retrying an already published npm version succeeds only when its bytes match; backfilling an older version does not move npm's latest tag backwards. To retry a failed publication, or publish a release whose older tag predates this workflow, run it manually on main with the published tag. After successful publication, install globally with npm install -g @opentig/cli@<version> and check opentig --version. Before publication, the downloaded draft tarball can be evaluated with npm install -g /absolute/path/opentig-cli-<version>.tgz; use a separate --home and port for evaluation. Installing the CLI does not start a server or install a service automatically.

Releases are unsigned by default and need no signing credentials. Windows may show an unknown publisher or SmartScreen warning, and device policies can block unsigned applications. Automatic updates still use HTTPS and SHA-512 download integrity checks, but do not verify a signing publisher.

To enable signing later, configure the release GitHub environment:

  • Variable WINDOWS_RELEASE_SIGNING: signed (unset or unsigned keeps unsigned releases).
  • Secret WINDOWS_CSC_LINK: the signing certificate accepted by electron-builder, normally a base64-encoded PFX, supplied privately through GitHub settings.
  • Secret WINDOWS_CSC_KEY_PASSWORD: the certificate password.
  • Variable WINDOWS_PUBLISHER_NAME: the exact certificate publisher/common name. The build requires signing and release verification checks Authenticode trust and the publisher on both the app and installer. The updater verifies downloaded installer signatures against this publisher.

The certificate is not currently provisioned. This integration supports a certificate-based signer; a hardware/cloud signing service requires its provider-specific configuration. When signed mode is selected, missing signing credentials fail the workflow explicitly; it never falls back to unsigned. Do not place credentials in source, PR jobs, or the client.

The update destination is the public jorgefl8/opentig repository, recorded in release.config.json. Public, unauthenticated GitHub Releases allow updates without a user token. No GitHub token is embedded in the application, and browser/server credentials are unrelated to release access. Drafts and prereleases are not offered by the stable updater. Before the first public release, validate installation and coexistence with Dev on Windows, perform an actual upgrade between two versions, and verify data preservation. These workflows do not change repository visibility.

Edit on GitHub