# winget-submit A Forgejo Actions step that submits a new release of a program to the `JCOllie` winget source, as a pull request against its manifest repository, [`jeff/winget-pkgs`](https://git.jcollie.dev/jeff/winget-pkgs). ```console git clone https://git.jcollie.dev/jeff/winget-submit.git ``` It is mirrored at . ## What it does Given a package identifier, a version and the URL of each installer, it: 1. clones `jeff/winget-pkgs` at `main`; 2. runs that repository's `wingetsource new-version`, which copies the package's newest version and replaces what changes with the release — the version, the release date, each installer's URL and SHA-256, and the release notes link; 3. commits the new version and runs `wingetsource check` on it, which downloads each installer and confirms its hash; 4. force-pushes the branch `submit//`, and opens a pull request titled ` ` unless one is already open for that branch. The pull request still needs `jeff/winget-pkgs`' own `test` check to pass and a merge by hand; branch protection there keeps the submitter off `main`. The manifest is never written here. Writing it is `wingetsource`'s job, and this action runs whatever `wingetsource` is on `main`, so a change to how manifests are written does not move the commit every program pins. A package's first version is still written by hand; this only submits a package that already has one, for the same set of architectures. ## Using it Pin it by commit, in a job after the one that uploads the release's assets. It submits whatever version it is given, so the workflow is what skips a prerelease — here, any tag with a `-` in it: ```yaml winget: needs: release if: ${{ !contains(forge.ref_name, '-') }} runs-on: nixos-do-s steps: # The tag is v0.3.0; the version is 0.3.0. - name: Version id: version run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - name: Submit to the JCOllie winget source uses: https://git.jcollie.dev/jeff/winget-submit@ with: identifier: JCOllie.Clipwatch version: ${{ steps.version.outputs.version }} installers: | x64 https://git.jcollie.dev/jeff/clipwatch/releases/download/${{ forge.ref_name }}/clipwatch-x86_64-windows.exe release-notes-url: https://git.jcollie.dev/jeff/clipwatch/releases/tag/${{ forge.ref_name }} token: ${{ secrets.WINGET_BOT_TOKEN }} ``` | Input | Required | Meaning | | --- | --- | --- | | `identifier` | yes | The package identifier, e.g. `JCOllie.Clipwatch`. | | `version` | yes | The version to submit. | | `installers` | yes | One ` ` per line, for exactly the architectures of the package's newest version. | | `product-codes` | no | One ` ` per line: a `ProductCode` to write instead of the one read from the new MSI. | | `release-notes-url` | no | The release's notes. Without it the new version has none. | | `release-date` | no | `YYYY-MM-DD`; today in UTC by default. | | `token` | yes, except for a dry run | The submitter's token: `secrets.WINGET_BOT_TOKEN`. | | `dry-run` | no | `true` writes and checks the new version, prints it, and pushes nothing. | An MSI built with `Product Id="*"` has a new `ProductCode` every release. `wingetsource new-version` never copies the old one: it reads the new one from the MSI it downloads, and refuses an MSI whose `UpgradeCode` is not the package's, so an MSI needs nothing passed for it. `product-codes` is only for writing a different code than the MSI carries. The job needs nothing but Nix: the action's script comes from this repository's flake, and `wingetsource` runs in `jeff/winget-pkgs`' own development shell. ### The submitter's token `WINGET_BOT_TOKEN` is a token for `winget-bot`, a restricted Forgejo user with write access to `jeff/winget-pkgs` and to nothing else, which can push branches and open pull requests there but not merge them. Each program has a token of its own, limited to `jeff/winget-pkgs` and to the `write:repository` and `write:issue` scopes. It is a secret on the program's repository, because a workflow's own `forge.token` reaches only the repository it runs in. The commit is authored as `winget-bot `, built into the action: a token limited to one repository cannot read its own user. `tools/setup-submitter` in `jeff/winget-pkgs` sets all of this up for a program, and is run again for each new one; its CONTRIBUTING.md says how. git is handed the token in an HTTP header through the environment, so it appears neither in the process list nor in the clone. ## Reporting issues Report issues and send pull requests at . See [`CONTRIBUTING.md`](CONTRIBUTING.md) for how to work on it. ## License MIT. The repository follows the [REUSE](https://reuse.software/) specification, and `reuse lint` passes. ## References cited - Forgejo. *Forgejo API access token handlers (routers/api/v1/utils/access_token.go)*, version v16.0.6. . - Forgejo. *Forgejo access token validation (services/authz/access_token.go)*, version v16.0.6. . - Forgejo. *Forgejo API description (templates/swagger/v1_json.tmpl)*, version v16.0.3. . - Git Project. *git-config Documentation*. Git. .