Skip to content

Commit e67af97

Browse files
Add WinGet CD workflow and maintainer setup docs
Automate Turso.CLI updates via wingetcreate on release, and document one-time winget-pkgs registration with official Microsoft links. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 6879af4 commit e67af97

7 files changed

Lines changed: 294 additions & 0 deletions

File tree

.github/workflows/winget.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Publish to WinGet
2+
3+
# Continuous delivery into microsoft/winget-pkgs via WingetCreate.
4+
# Docs for maintainers: docs/winget.md
5+
# Official CD overview: https://github.com/microsoft/winget-create#using-windows-package-manager-manifest-creator-in-a-cicd-pipeline
6+
# Token setup: https://aka.ms/winget-create-token
7+
8+
on:
9+
release:
10+
types: [published]
11+
workflow_dispatch:
12+
inputs:
13+
tag:
14+
description: Release tag to publish (e.g. v1.0.31). Leave empty to use the latest non-prerelease release.
15+
required: false
16+
type: string
17+
submit:
18+
description: Submit a PR to microsoft/winget-pkgs (requires WINGET_TOKEN secret)
19+
required: false
20+
type: boolean
21+
default: false
22+
23+
permissions:
24+
contents: read
25+
26+
jobs:
27+
winget:
28+
name: Submit Turso.CLI to WinGet
29+
runs-on: windows-latest
30+
# Skip prereleases on the automatic release trigger
31+
if: ${{ github.event_name == 'workflow_dispatch' || !github.event.release.prerelease }}
32+
# Prefer the env var over --token so the PAT is not logged on the CLI.
33+
# https://aka.ms/winget-create-token
34+
env:
35+
WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
36+
PACKAGE_ID: Turso.CLI
37+
steps:
38+
- name: Resolve release assets
39+
id: release
40+
shell: pwsh
41+
run: |
42+
if ("${{ github.event_name }}" -eq "release") {
43+
$tag = "${{ github.event.release.tag_name }}"
44+
$assetsJson = '${{ toJSON(github.event.release.assets) }}'
45+
$assets = $assetsJson | ConvertFrom-Json
46+
} else {
47+
$env:GH_TOKEN = $env:GITHUB_TOKEN
48+
$tag = "${{ inputs.tag }}".Trim()
49+
if ([string]::IsNullOrWhiteSpace($tag)) {
50+
$release = gh release view --json tagName,assets | ConvertFrom-Json
51+
} else {
52+
$release = gh release view $tag --json tagName,assets | ConvertFrom-Json
53+
}
54+
$tag = $release.tagName
55+
$assets = $release.assets
56+
}
57+
58+
$version = $tag.TrimStart('v')
59+
$x64 = $assets | Where-Object { $_.name -eq "turso-cli_Windows_x86_64.zip" } | Select-Object -First 1
60+
$arm64 = $assets | Where-Object { $_.name -eq "turso-cli_Windows_arm64.zip" } | Select-Object -First 1
61+
62+
if (-not $x64 -or -not $arm64) {
63+
$names = ($assets | ForEach-Object { $_.name }) -join ", "
64+
throw "Missing Windows zip assets on $tag. Expected turso-cli_Windows_x86_64.zip and turso-cli_Windows_arm64.zip. Found: $names"
65+
}
66+
67+
"tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
68+
"version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
69+
"x64_url=$($x64.browser_download_url)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
70+
"arm64_url=$($arm64.browser_download_url)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
71+
Write-Host "Publishing $env:PACKAGE_ID $version"
72+
Write-Host "x64: $($x64.browser_download_url)"
73+
Write-Host "arm64: $($arm64.browser_download_url)"
74+
75+
- name: Download WingetCreate
76+
shell: pwsh
77+
run: |
78+
curl.exe -fsSL -JLO https://aka.ms/wingetcreate/latest
79+
Get-Item .\wingetcreate.exe | Format-List Name, Length
80+
81+
- name: Update WinGet manifest
82+
shell: pwsh
83+
run: |
84+
$submit = $false
85+
if ("${{ github.event_name }}" -eq "release") {
86+
$submit = $true
87+
} elseif ("${{ inputs.submit }}" -eq "true") {
88+
$submit = $true
89+
}
90+
91+
if ($submit -and [string]::IsNullOrWhiteSpace($env:WINGET_CREATE_GITHUB_TOKEN)) {
92+
throw "WINGET_TOKEN repository secret is required to submit. See docs/winget.md"
93+
}
94+
95+
$args = @(
96+
"update", $env:PACKAGE_ID,
97+
"--version", "${{ steps.release.outputs.version }}",
98+
"--urls",
99+
"${{ steps.release.outputs.x64_url }}",
100+
"${{ steps.release.outputs.arm64_url }}"
101+
)
102+
if ($submit) {
103+
$args += "--submit"
104+
}
105+
106+
Write-Host "Running: .\wingetcreate.exe $($args -join ' ')"
107+
& .\wingetcreate.exe @args
108+
if ($LASTEXITCODE -ne 0) {
109+
throw "wingetcreate exited with code $LASTEXITCODE"
110+
}

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ To upgrade an existing installation of the CLI, run:
3333
brew upgrade turso
3434
```
3535

36+
#### [WinGet](https://learn.microsoft.com/windows/package-manager/winget/) (Windows)
37+
38+
```powershell
39+
winget install Turso.CLI
40+
```
41+
42+
Requires the package to be published in the
43+
[WinGet community repository](https://github.com/microsoft/winget-pkgs).
44+
Maintainer setup and CD: [docs/winget.md](docs/winget.md).
45+
3646
### Install script
3747

3848
#### macOS / Linux

docs/winget.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
## Publishing Turso CLI to WinGet
2+
3+
WinGet packages live in the community repository [`microsoft/winget-pkgs`](https://github.com/microsoft/winget-pkgs).
4+
After the package exists once, this repo’s [Publish to WinGet](../.github/workflows/winget.yml) workflow updates it on every stable GitHub Release.
5+
6+
Package id: `Turso.CLI`
7+
8+
```powershell
9+
winget install Turso.CLI
10+
```
11+
12+
### Official documentation
13+
14+
- Create a package manifest: <https://learn.microsoft.com/windows/package-manager/package/manifest>
15+
- Submit the manifest (first-time registration): <https://learn.microsoft.com/windows/package-manager/package/repository>
16+
- Authoring rules / directory layout: <https://github.com/microsoft/winget-pkgs/blob/master/doc/Authoring.md>
17+
- WingetCreate (create / update / submit): <https://github.com/microsoft/winget-create>
18+
- WingetCreate in CI/CD: <https://github.com/microsoft/winget-create#using-windows-package-manager-manifest-creator-in-a-cicd-pipeline>
19+
- GitHub token for CI (use `WINGET_CREATE_GITHUB_TOKEN`, not `--token` on the CLI): <https://aka.ms/winget-create-token>
20+
- Update command reference: <https://github.com/microsoft/winget-create/blob/main/doc/update.md>
21+
- Policies: <https://learn.microsoft.com/windows/package-manager/package/windows-package-manager-policies>
22+
23+
### One-time setup (maintainers)
24+
25+
Do this once after a release that includes native Windows assets
26+
(`turso-cli_Windows_x86_64.zip` and `turso-cli_Windows_arm64.zip` from GoReleaser).
27+
28+
1. **Create the first manifests** (interactive is fine):
29+
30+
```powershell
31+
winget install wingetcreate
32+
wingetcreate new `
33+
https://github.com/tursodatabase/turso-cli/releases/download/vX.Y.Z/turso-cli_Windows_x86_64.zip `
34+
https://github.com/tursodatabase/turso-cli/releases/download/vX.Y.Z/turso-cli_Windows_arm64.zip
35+
```
36+
37+
Use publisher `Turso`, package name `CLI` so the id is `Turso.CLI`.
38+
Installer type should be `zip` with nested portable `turso.exe` (see `winget/` for a template).
39+
40+
2. **Validate and open the first PR** against `microsoft/winget-pkgs` (or let WingetCreate submit):
41+
42+
```powershell
43+
winget validate --manifest .\manifests\t\Turso\CLI\<version>
44+
```
45+
46+
Follow the submit guide: <https://learn.microsoft.com/windows/package-manager/package/repository>
47+
48+
3. **Create a classic GitHub PAT** with the `public_repo` scope (fine-grained tokens are not supported by WingetCreate). Optional: `delete_repo` so failed forks can be cleaned up.
49+
Steps: <https://github.com/microsoft/winget-create/blob/main/doc/token.md>
50+
51+
4. **Add a repository secret** on `tursodatabase/turso-cli`:
52+
53+
- Name: `WINGET_TOKEN`
54+
- Value: the classic PAT from step 3
55+
56+
GitHub docs: <https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository>
57+
58+
5. **Merge the first `winget-pkgs` PR**. After it lands, every later stable release can be automated.
59+
60+
### Continuous deployment
61+
62+
On each stable `release` (`published`, non-prerelease), `.github/workflows/winget.yml`:
63+
64+
1. Resolves `turso-cli_Windows_x86_64.zip` and `turso-cli_Windows_arm64.zip` from the release
65+
2. Downloads WingetCreate from <https://aka.ms/wingetcreate/latest>
66+
3. Runs `wingetcreate update Turso.CLI --version <ver> --urls <x64> <arm64> --submit`
67+
68+
The workflow also supports `workflow_dispatch` for a dry run (`submit: false`) or a manual submit.
69+
70+
Reference implementations from the WingetCreate README:
71+
72+
- <https://github.com/microsoft/edit/blob/main/.github/workflows/winget.yml>
73+
- <https://github.com/microsoft/terminal/blob/main/.github/workflows/winget.yml>
74+
75+
### Local smoke test (optional)
76+
77+
```powershell
78+
winget settings --enable LocalManifestFiles
79+
winget install --manifest .\winget\manifests\0.0.0-template
80+
```
81+
82+
Sandbox testing from a `winget-pkgs` checkout: <https://learn.microsoft.com/windows/package-manager/package/repository#step-2-test-your-manifest-with-windows-sandbox>

winget/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# WinGet package templates for Turso.CLI
2+
3+
Seed manifests for the **first** submission to [`microsoft/winget-pkgs`](https://github.com/microsoft/winget-pkgs).
4+
5+
After the package exists, do **not** hand-edit these for every release — the
6+
[Publish to WinGet](../.github/workflows/winget.yml) workflow uses
7+
[`wingetcreate update`](https://github.com/microsoft/winget-create/blob/main/doc/update.md).
8+
9+
Maintainer instructions: [docs/winget.md](../docs/winget.md)
10+
11+
## Before opening the first PR
12+
13+
1. Ship a Turso CLI GitHub Release that includes:
14+
- `turso-cli_Windows_x86_64.zip`
15+
- `turso-cli_Windows_arm64.zip`
16+
2. Copy `manifests/0.0.0-template` to a real version directory name (for example `1.0.31`).
17+
3. Replace `PackageVersion`, `InstallerUrl`, `InstallerSha256`, and `ReleaseDate`.
18+
4. Compute hashes:
19+
20+
```powershell
21+
Get-FileHash .\turso-cli_Windows_x86_64.zip -Algorithm SHA256
22+
Get-FileHash .\turso-cli_Windows_arm64.zip -Algorithm SHA256
23+
```
24+
25+
5. Validate:
26+
27+
```powershell
28+
winget validate --manifest .\manifests\<version>
29+
```
30+
31+
6. Submit under `manifests/t/Turso/CLI/<version>/` in `winget-pkgs`
32+
(<https://learn.microsoft.com/windows/package-manager/package/repository>).
33+
34+
Or skip the templates and run `wingetcreate new <x64-url> <arm64-url>` instead.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.10.0.schema.json
2+
#
3+
# Replace InstallerUrl / InstallerSha256 with values from a real GitHub Release
4+
# that contains turso-cli_Windows_x86_64.zip and turso-cli_Windows_arm64.zip.
5+
# NestedInstallerFiles matches the GoReleaser zip layout (turso.exe at archive root).
6+
PackageIdentifier: Turso.CLI
7+
PackageVersion: 0.0.0-template
8+
InstallerLocale: en-US
9+
InstallerType: zip
10+
NestedInstallerType: portable
11+
NestedInstallerFiles:
12+
- RelativeFilePath: turso.exe
13+
PortableCommandAlias: turso
14+
Commands:
15+
- turso
16+
UpgradeBehavior: install
17+
ReleaseDate: 2099-01-01
18+
Installers:
19+
- Architecture: x64
20+
InstallerUrl: https://github.com/tursodatabase/turso-cli/releases/download/v0.0.0/turso-cli_Windows_x86_64.zip
21+
InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000
22+
- Architecture: arm64
23+
InstallerUrl: https://github.com/tursodatabase/turso-cli/releases/download/v0.0.0/turso-cli_Windows_arm64.zip
24+
InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000
25+
ManifestType: installer
26+
ManifestVersion: 1.10.0
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.10.0.schema.json
2+
PackageIdentifier: Turso.CLI
3+
PackageVersion: 0.0.0-template
4+
PackageLocale: en-US
5+
Publisher: Turso
6+
PublisherUrl: https://turso.tech
7+
PublisherSupportUrl: https://github.com/tursodatabase/turso-cli/issues
8+
Author: Turso
9+
PackageName: Turso CLI
10+
PackageUrl: https://docs.turso.tech/cli
11+
License: MIT
12+
LicenseUrl: https://github.com/tursodatabase/turso-cli/blob/main/LICENSE
13+
Copyright: Copyright (c) Turso / ChiselStrike, Inc.
14+
ShortDescription: Command line interface for Turso Cloud
15+
Description: The Turso CLI manages Turso Cloud databases, authentication, groups, and local development workflows from Windows, macOS, and Linux.
16+
Moniker: turso
17+
Tags:
18+
- cli
19+
- cloud
20+
- database
21+
- libsql
22+
- sqlite
23+
- turso
24+
ReleaseNotesUrl: https://github.com/tursodatabase/turso-cli/releases
25+
ManifestType: defaultLocale
26+
ManifestVersion: 1.10.0
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.10.0.schema.json
2+
PackageIdentifier: Turso.CLI
3+
PackageVersion: 0.0.0-template
4+
DefaultLocale: en-US
5+
ManifestType: version
6+
ManifestVersion: 1.10.0

0 commit comments

Comments
 (0)