Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/winget-package-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: WinGet Package Publish

on:
workflow_dispatch:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
winget-package:
name: Build WinGet portable package
runs-on: windows-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Run tests
run: uv run pytest

- name: Build Python wheel
run: uv build

- name: Build devspec.exe
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$wheel = Get-ChildItem dist -Filter "*.whl" | Select-Object -First 1
if (-not $wheel) {
throw "No wheel found in dist."
}

uv venv .venv-winget --python 3.12 --clear
uv pip install --python .\.venv-winget\Scripts\python.exe "pyinstaller>=6.0" $wheel.FullName

New-Item -ItemType Directory -Force -Path build\winget | Out-Null
@(
"from devspec_installer.cli import main"
""
"raise SystemExit(main())"
) | Set-Content -Path build\winget\devspec-entry.py -Encoding UTF8

.\.venv-winget\Scripts\pyinstaller.exe `
--noconfirm `
--clean `
--onefile `
--name devspec `
--distpath dist\winget `
--workpath build\pyinstaller `
--specpath build\pyinstaller `
--collect-data devspec_installer `
build\winget\devspec-entry.py

- name: Smoke test devspec.exe
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$target = Join-Path $env:RUNNER_TEMP "devspec-winget-smoke"
New-Item -ItemType Directory -Force -Path $target | Out-Null

.\dist\winget\devspec.exe version
.\dist\winget\devspec.exe init --target $target --profile core --repo-state existing
.\dist\winget\devspec.exe doctor --target $target --profile core

- name: Compute devspec.exe SHA256
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$hash = (Get-FileHash dist\winget\devspec.exe -Algorithm SHA256).Hash.ToLowerInvariant()
"$hash devspec.exe" | Set-Content -Path dist\winget\devspec.exe.sha256 -Encoding ASCII

$manifest = Get-Content packaging\winget\devspec.yaml -Raw
$manifest = $manifest.Replace("REPLACE_WITH_RELEASE_SHA256", $hash)
$manifest | Set-Content -Path dist\winget\devspec.yaml -Encoding UTF8

Write-Host "devspec.exe SHA256: $hash"

- name: Upload WinGet package artifacts
uses: actions/upload-artifact@v4
with:
name: devspec-winget-package
path: |
dist/winget/devspec.exe
dist/winget/devspec.exe.sha256
dist/winget/devspec.yaml

- name: Attach WinGet package artifacts
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: |
dist/winget/devspec.exe
dist/winget/devspec.exe.sha256
dist/winget/devspec.yaml
20 changes: 18 additions & 2 deletions docs/how-to/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -506,14 +506,30 @@ powershell -ExecutionPolicy Bypass -File scripts/test-local-install.ps1
bash scripts/test-local-install.sh
```

Use provider-specific GitHub workflow filenames and display names. The current Python package workflows are:
Use provider-specific GitHub workflow filenames and display names. The current package-provider workflows are:

```text
.github/workflows/python-package-ci.yml
.github/workflows/python-package-publish.yml
.github/workflows/winget-package-publish.yml
```

Future package-provider workflows should follow the same pattern, such as `homebrew-package-publish.yml`, `winget-package-publish.yml`, or `npm-package-publish.yml`.
Future package-provider workflows should follow the same pattern, such as `homebrew-package-publish.yml` or `npm-package-publish.yml`.

For WinGet releases, publish the Windows portable executable from GitHub Releases and submit the generated manifest to `microsoft/winget-pkgs`:

```text
dist/winget/devspec.exe
dist/winget/devspec.exe.sha256
dist/winget/devspec.yaml
```

Validate the generated manifest on Windows before submission:

```text
winget validate <path-to-generated-devspec.yaml>
winget install --manifest <path-to-generated-devspec.yaml>
```

When adapter files are added, removed, or moved, update:

Expand Down
8 changes: 4 additions & 4 deletions docs/how-to/setup/winget.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Use this guide on Windows when your machine allows approved WinGet packages. WinGet is Windows' package installer for command-line and desktop tools.

The WinGet package identifier is a placeholder until the public package is finalized.
The planned public WinGet package identifier is `SpecLabs.Devspec`. Until Microsoft approves the package submission, use `uvx devspec ...` or manual copy as the fallback.

## Before You Start

Expand Down Expand Up @@ -31,7 +31,7 @@ cd D:\code\my-app
Install the CLI:

```text
winget install <publisher>.devspec
winget install SpecLabs.Devspec
```

Install devspec files into your repository:
Expand Down Expand Up @@ -122,7 +122,7 @@ devspec init --target D:\code\my-app --profile all --repo-state existing
| Argument | Meaning | Beginner explanation |
| --- | --- | --- |
| `winget --version` | Print the WinGet version. | Confirms WinGet is available on the machine. |
| `winget install <publisher>.devspec` | Install the devspec CLI. | The `<publisher>` placeholder will become the real WinGet publisher/package ID after release. |
| `winget install SpecLabs.Devspec` | Install the devspec CLI. | Installs the approved WinGet package after Microsoft accepts the package submission. |
| `version` | Print the devspec CLI version. | Use this to confirm the command runs. It does not change files. |
| `init` | Install devspec files. | Copies framework files into your repo. |
| `--target .` | Target repo folder. | `.` means the folder your terminal is currently in. |
Expand All @@ -139,7 +139,7 @@ devspec init --target D:\code\my-app --profile all --repo-state existing
| Problem | What to try |
| --- | --- |
| `winget` is not found. | Use Windows App Installer or ask your IT team whether WinGet is disabled. |
| `<publisher>.devspec` is not found. | The package ID may still be a placeholder. Use `uvx devspec ...` until the package is published. |
| `SpecLabs.Devspec` is not found. | The package may still be awaiting Microsoft approval. Use `uvx devspec ...` until the package is published. |
| `devspec` is not found after install. | Close and reopen PowerShell so PATH changes reload. |
| PowerShell blocks a command. | Ask your team about execution policy or approved package sources. |
| Corporate software policy blocks WinGet. | Use [uv and uvx](uv.md) if allowed, or [manual copy](manual-copy.md). |
6 changes: 3 additions & 3 deletions packaging/winget/devspec.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
PackageIdentifier: OWNER.devspec
PackageIdentifier: SpecLabs.Devspec
PackageVersion: 0.1.0
PackageLocale: en-US
Publisher: devspec contributors
Publisher: SpecLabs
PackageName: devspec
License: Apache-2.0
ShortDescription: Installer and synchronizer CLI for the devspec workflow framework.
Installers:
- Architecture: x64
InstallerType: portable
InstallerUrl: https://github.com/OWNER/devspec/releases/download/v0.1.0/devspec.exe
InstallerUrl: https://github.com/speclabs/devspec/releases/download/v0.1.0/devspec.exe
InstallerSha256: REPLACE_WITH_RELEASE_SHA256
ManifestType: singleton
ManifestVersion: 1.6.0
Loading