Skip to content
Closed
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
82 changes: 82 additions & 0 deletions .github/workflows/winget-bootstrap.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: WinGet bootstrap (one-off, delete after use)

on:
push:
branches: ["ci/winget-bootstrap"]

jobs:
bootstrap:
runs-on: windows-latest
steps:
Comment on lines +7 to +10

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restrict workflow permissions to minimum required scope.

The workflow runs with default broad permissions. For security, explicitly set minimal permissions. Since this workflow only downloads external tools and doesn't interact with the repository, consider:

jobs:
  bootstrap:
    runs-on: windows-latest
    permissions:
      contents: read

Or if no repository access is needed:

jobs:
  bootstrap:
    runs-on: windows-latest
    permissions: {}
🧰 Tools
🪛 zizmor (1.25.2)

[info] 8-8: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/winget-bootstrap.yml around lines 7 - 10, The workflow's
job "bootstrap" currently relies on default broad permissions; add an explicit
minimal permissions block under the bootstrap job definition (the job named
bootstrap in the workflow) — either set permissions: { contents: read } if read
access is needed or permissions: {} if no repo access is required — so the job
no longer inherits wide default permissions.

- name: Generate manifests and submit to winget-pkgs
shell: pwsh
env:
WINGET_TOKEN: ${{ secrets.WINGET_SUBMIT_TOKEN }}
run: |
$ErrorActionPreference = "Stop"
Comment on lines +14 to +16

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add token validation before proceeding.

The reference workflow (winget.yml) validates the token is set before use. This avoids a cryptic wingetcreate failure if the secret is misconfigured.

Proposed fix
         run: |
           $ErrorActionPreference = "Stop"
+          if (-not $env:WINGET_TOKEN) {
+            throw "WINGET_SUBMIT_TOKEN is not configured"
+          }
           $version    = "0.30.0"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/winget-bootstrap.yml around lines 14 - 16, Add an explicit
validation for the WINGET_TOKEN secret before running the rest of the script:
inside the run block that currently sets $ErrorActionPreference, check the
WINGET_TOKEN environment variable (WINGET_TOKEN) and fail early with a clear
error message if it is null/empty so the job exits before calling wingetcreate;
update the run step that contains $ErrorActionPreference = "Stop" to include
this guard and return a non-zero exit when the token is missing.

$version = "0.30.0"
$pkgId = "PythoughtsLabs.PythinkerCode"
$installerUrl = "https://github.com/Pythoughts-labs/pythinker-code/releases/download/v$version/PythinkerSetup-$version.exe"

$wcUrl = "https://github.com/microsoft/winget-create/releases/download/v1.12.8.0/wingetcreate.exe"
$wcSha = "8BD738851B524885410112678E3771B341C5C716DE60FBBECB88AB0A363ED85D"
Invoke-WebRequest -Uri $wcUrl -OutFile wingetcreate.exe
if ((Get-FileHash wingetcreate.exe -Algorithm SHA256).Hash -ne $wcSha) { throw "hash mismatch" }

$sha256 = [System.Text.Encoding]::UTF8.GetString((Invoke-WebRequest -Uri "$installerUrl.sha256").Content).Trim().Split()[0]
Write-Host "SHA256: $sha256"

Invoke-WebRequest -Uri $installerUrl -OutFile installer.exe
$header = [System.Text.Encoding]::ASCII.GetString([System.IO.File]::ReadAllBytes("installer.exe")[0..65535])
$installerType = if ($header -match "Inno Setup") { "inno" } elseif ($header -match "Nullsoft") { "nullsoft" } else { "exe" }
$silentSwitch = if ($installerType -eq "inno") { "/VERYSILENT /NORESTART" } else { "/S" }
Write-Host "Installer type: $installerType"

$dir = "manifests\p\PythoughtsLabs\PythinkerCode\$version"
New-Item -ItemType Directory -Force -Path $dir | Out-Null

@("PackageIdentifier: $pkgId",
"PackageVersion: $version",
"DefaultLocale: en-US",
"ManifestType: version",
"ManifestVersion: 1.6.0") -join "`n" |
Set-Content -Path "$dir\$pkgId.yaml" -Encoding UTF8

@("PackageIdentifier: $pkgId",
"PackageVersion: $version",
"Platform:",
"- Windows.Desktop",
"MinimumOSVersion: 10.0.17763.0",
"InstallerType: $installerType",
"Installers:",
"- Architecture: x64",
" InstallerUrl: $installerUrl",
" InstallerSha256: $sha256",
" InstallerSwitches:",
" Silent: $silentSwitch",
" SilentWithProgress: $silentSwitch",
"ManifestType: installer",
"ManifestVersion: 1.6.0") -join "`n" |
Set-Content -Path "$dir\$pkgId.installer.yaml" -Encoding UTF8

@("PackageIdentifier: $pkgId",
"PackageVersion: $version",
"PackageLocale: en-US",
"Publisher: Pythoughts Labs",
"PublisherUrl: https://pythinker.com",
"PackageName: Pythinker Code",
"PackageUrl: https://pythinker.com",
"License: Apache-2.0",
"LicenseUrl: https://github.com/Pythoughts-labs/pythinker-code/blob/main/LICENSE",
"ShortDescription: Terminal-native review-first AI engineering agent",
"Moniker: pythinker",
"Tags:",
"- ai",
"- agent",
"- cli",
"ManifestType: defaultLocale",
"ManifestVersion: 1.6.0") -join "`n" |
Set-Content -Path "$dir\$pkgId.locale.en-US.yaml" -Encoding UTF8

Write-Host "Generated:"; Get-ChildItem $dir
.\wingetcreate.exe submit $dir --token $env:WINGET_TOKEN
Loading