diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1373f7b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,83 @@ +name: Release + +# Manual, because the version lives in tauri.conf.json and a release is a decision, not a +# consequence of merging. Bump it in a pull request, then run this. +on: + workflow_dispatch: + +permissions: + contents: write + +jobs: + windows: + name: Installer + runs-on: windows-latest + + steps: + - uses: actions/checkout@v5 + with: + ref: main + fetch-depth: 0 + + - uses: actions/setup-node@v6 + with: + node-version: 22 + cache: npm + + - uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-pc-windows-msvc + + - uses: Swatinem/rust-cache@v2 + with: + workspaces: src-tauri + + - run: npm ci + + # The same gate as CI. A release that skips it is the one build nobody checked. + - run: npm run check + - run: npm test + - run: cargo test --manifest-path src-tauri/Cargo.toml + + - name: Read the version, and refuse a tag that exists + id: version + shell: pwsh + run: | + $version = (Get-Content src-tauri/tauri.conf.json -Raw | ConvertFrom-Json).version + if (-not $version) { Write-Error 'No version in src-tauri/tauri.conf.json'; exit 1 } + # Checked here rather than at `git tag` half an hour later, once the installer is built. + if (git tag -l "v$version") { Write-Error "v$version is already tagged"; exit 1 } + "version=$version" >> $env:GITHUB_OUTPUT + + - name: Build the installer + run: npx tauri build + + - name: Collect it + id: artifact + shell: pwsh + run: | + New-Item -ItemType Directory -Force artifacts | Out-Null + $setup = Get-ChildItem src-tauri/target/release/bundle/nsis/*-setup.exe | Select-Object -First 1 + if (-not $setup) { Write-Error 'tauri build produced no NSIS installer'; exit 1 } + Copy-Item $setup.FullName artifacts/ + Get-ChildItem artifacts | Format-Table Name, Length + + - name: Tag it + shell: pwsh + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git tag -a "v${{ steps.version.outputs.version }}" -m "Release v${{ steps.version.outputs.version }}" + git push origin "v${{ steps.version.outputs.version }}" + + # Notes from release-notes/v.md when it is there, and GitHub's own summary of the + # commits when it is not — a missing file should not lose a built installer. + - name: Publish + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ steps.version.outputs.version }} + name: OpenThemeGenerator ${{ steps.version.outputs.version }} + body_path: release-notes/v${{ steps.version.outputs.version }}.md + generate_release_notes: true + fail_on_unmatched_files: true + files: artifacts/*-setup.exe diff --git a/README.md b/README.md index c4095e3..2432d7f 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,11 @@ npm run start The workflow runs the table above — lint, types, tests and build on Linux, and `cargo fmt`, `clippy` and the host's tests on Windows, where the app actually ships. +Releases are manual. Bump `version` in `src-tauri/tauri.conf.json` in a pull request, then run the +**Release** workflow: it runs the same gate, builds the NSIS installer, tags `v` and +publishes it. Notes come from `release-notes/v.md` if you wrote one, and from GitHub's +summary of the commits if you did not. + Two things the tests care about more than style: - **Every theme this app derives clears 4.5:1** on every surface/label pair, in both modes. So does diff --git a/package-lock.json b/package-lock.json index 6c05613..3a974cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1988,9 +1988,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index ba22ea7..8c65401 100644 --- a/package.json +++ b/package.json @@ -54,5 +54,8 @@ "vite": "^8.2.0", "vitest": "^4.1.10", "zod": "^4.4.3" + }, + "overrides": { + "cookie": "^0.7.2" } }