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
25 changes: 25 additions & 0 deletions .github/workflows/winget-manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: WinGet manifest

# Gera e valida os manifestos do WinGet de uma release já publicada (#273). Nunca envia nada ao repositório da Microsoft.
on:
workflow_dispatch:
inputs:
tag:
description: "Release tag already published (e.g. v0.12.0-alpha.1)"
required: true

permissions:
contents: read

jobs:
manifest:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Generate and validate manifests
shell: pwsh
run: .\build\New-WingetManifest.ps1 -Tag "${{ inputs.tag }}" -OutDir artifacts\winget
- uses: actions/upload-artifact@v4
with:
name: winget-manifests
path: artifacts/winget
102 changes: 102 additions & 0 deletions build/New-WingetManifest.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<#
.SYNOPSIS
Gera os manifestos do WinGet (#273) de uma release publicada do ControlFS e, onde o winget existir, valida.
Não envia nada para o repositório da Microsoft: o envio é um passo manual e consciente (docs/build-and-release.md).
.EXAMPLE
.\build\New-WingetManifest.ps1 -Tag v0.12.0-alpha.1 -OutDir artifacts\winget
#>
param(
[Parameter(Mandatory)][string]$Tag,
[string]$OutDir = "artifacts\winget",
[string]$Repo = "nextestudios/ControlFS"
)
$ErrorActionPreference = "Stop"

$version = $Tag.TrimStart("v")
$installerName = "ControlFS-Setup-x64.exe"
$url = "https://github.com/$Repo/releases/download/$Tag/$installerName"

# O hash é do arquivo que a release realmente publica (nunca de uma compilação local): baixa e calcula.
$work = Join-Path ([System.IO.Path]::GetTempPath()) ("controlfs-winget-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Force -Path $work | Out-Null
try {
$download = Join-Path $work $installerName
Invoke-WebRequest -Uri $url -OutFile $download -UseBasicParsing
$sha = (Get-FileHash -Algorithm SHA256 -LiteralPath $download).Hash.ToUpperInvariant()
}
finally {
Remove-Item -Recurse -Force -LiteralPath $work -ErrorAction SilentlyContinue
}

$id = "nextestudios.ControlFS"
$schema = "1.9.0"
$date = (Get-Date).ToString("yyyy-MM-dd")
$dir = Join-Path $OutDir "manifests\n\nextestudios\ControlFS\$version"
New-Item -ItemType Directory -Force -Path $dir | Out-Null

$header = "# yaml-language-server: `$schema=https://aka.ms/winget-manifest.{0}.{1}.schema.json"

@"
$($header -f "version", $schema)
PackageIdentifier: $id
PackageVersion: $version
DefaultLocale: en-US
ManifestType: version
ManifestVersion: $schema
"@ | Set-Content -Encoding utf8 (Join-Path $dir "$id.yaml")

@"
$($header -f "installer", $schema)
PackageIdentifier: $id
PackageVersion: $version
InstallerType: inno
Scope: user
InstallModes:
- interactive
- silent
- silentWithProgress
UpgradeBehavior: install
MinimumOSVersion: 10.0.19041.0
ReleaseDate: $date
Installers:
- Architecture: x64
InstallerUrl: $url
InstallerSha256: $sha
ManifestType: installer
ManifestVersion: $schema
"@ | Set-Content -Encoding utf8 (Join-Path $dir "$id.installer.yaml")

@"
$($header -f "defaultLocale", $schema)
PackageIdentifier: $id
PackageVersion: $version
PackageLocale: en-US
Publisher: nextestudios
PublisherUrl: https://github.com/$Repo
PublisherSupportUrl: https://github.com/$Repo/issues
PackageName: ControlFS
PackageUrl: https://github.com/$Repo
License: AGPL-3.0-only
LicenseUrl: https://github.com/$Repo/blob/main/LICENSE
ShortDescription: Controller-first file manager for Windows.
Description: ControlFS is a native Windows file manager you can drive entirely with a game controller (or keyboard and mouse), with tabs, dual pane, archives, previews and a built-in media player.
Moniker: controlfs
Tags:
- file-manager
- gamepad
- controller
- explorer
- archive
ReleaseNotesUrl: https://github.com/$Repo/releases/tag/$Tag
ManifestType: defaultLocale
ManifestVersion: $schema
"@ | Set-Content -Encoding utf8 (Join-Path $dir "$id.locale.en-US.yaml")

Write-Host "Manifestos em $dir (SHA-256 do instalador: $sha)"

if (Get-Command winget -ErrorAction SilentlyContinue) {
winget validate --manifest $dir
if ($LASTEXITCODE -ne 0) { throw "winget validate falhou ($LASTEXITCODE)" }
} else {
Write-Warning "winget não encontrado: manifestos gerados, mas não validados."
}
10 changes: 10 additions & 0 deletions docs/build-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,13 @@ Na próxima release, confira no log "Release será assinada (provedor: …)" e a
atualize `docs/CODE_SIGNING.md` (que ainda diz "ainda não têm assinatura"). O desinstalador do Inno Setup
(`unins000.exe`) não é assinado nesta etapa.


## WinGet (#273)

O pacote do WinGet é `nextestudios.ControlFS` (instalador Inno por usuário, x64, sem administrador). O manifesto **sempre** vem de uma release já publicada: nunca se envia um pacote antes de o instalador oficial existir na URL da release.

- **Gerar e validar:** Actions → **WinGet manifest** → Run workflow com a tag (ex.: `v0.12.0-alpha.1`). O workflow baixa o `ControlFS-Setup-x64.exe` da release, calcula o SHA-256, gera os três manifestos (`version`, `installer`, `defaultLocale`) com `build/New-WingetManifest.ps1`, roda `winget validate` e guarda o resultado no artefato `winget-manifests`. Não envia nada para fora. Localmente (Windows): `.\build\New-WingetManifest.ps1 -Tag v0.12.0-alpha.1`.
- **Enviar (passo manual, por quem é dono do pacote):** copiar a pasta `manifests\n\nextestudios\ControlFS\<versão>` do artefato para um fork de `microsoft/winget-pkgs` e abrir o PR (ou `wingetcreate submit`), respondendo à revisão. Só depois de aceito o pacote aparece no catálogo.
- **A cada release estável nova:** repetir os dois passos acima com a nova tag. O `AppId` do instalador nunca muda, então `winget upgrade` atualiza a mesma instalação sem mexer nas preferências (ficam em `%LOCALAPPDATA%\ControlFS`).
- **Depois de aceito:** documentar `winget install nextestudios.ControlFS` e `winget upgrade nextestudios.ControlFS` no README. Instalação direta, portátil e atualização dentro do app continuam como estão.
- **Sem assinatura (#84):** o instalador ainda não é assinado; o WinGet aceita, mas o SmartScreen pode avisar. A aprovação e a primeira verificação ficam melhores depois da assinatura.
Loading