-
Notifications
You must be signed in to change notification settings - Fork 0
Set up Snap and Winget distribution workflows #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| name: Snap | ||
|
|
||
| on: | ||
| release: | ||
| types: | ||
| - published | ||
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: Existing GitHub release tag like v0.0.102. Leave empty for artifact-only builds. | ||
| required: false | ||
| type: string | ||
| publish: | ||
| description: Publish the built snap to the Snap Store. | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
| release_channel: | ||
| description: Snap Store channel to release to. | ||
| required: false | ||
| type: choice | ||
| default: stable | ||
| options: | ||
| - stable | ||
| - candidate | ||
| - beta | ||
| - edge | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| snap: | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} | ||
| steps: | ||
| - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 | ||
|
|
||
| - name: Resolve release metadata | ||
| id: meta | ||
| shell: bash | ||
| run: | | ||
| if [[ "${GITHUB_EVENT_NAME}" == "release" ]]; then | ||
| TAG="${{ github.event.release.tag_name }}" | ||
| else | ||
| TAG="${{ inputs.tag }}" | ||
| fi | ||
|
|
||
| VERSION="$(python -c "import json; print(json.load(open('package.json'))['version'])")" | ||
| if [[ -n "$TAG" ]]; then | ||
| VERSION="${TAG#v}" | ||
| fi | ||
|
|
||
| CHANNEL="stable" | ||
| if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then | ||
| CHANNEL="${{ inputs.release_channel }}" | ||
| fi | ||
|
|
||
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT" | ||
| echo "DORA_RELEASE_VERSION=$VERSION" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Build snap | ||
| uses: snapcore/action-build@v1 | ||
| id: build | ||
|
|
||
| - name: Upload snap artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: dora-snap-${{ steps.meta.outputs.version }} | ||
| path: ${{ steps.build.outputs.snap }} | ||
|
|
||
| - name: Upload snap to GitHub release | ||
| if: ${{ steps.meta.outputs.tag != '' }} | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: gh release upload ${{ steps.meta.outputs.tag }} ${{ steps.build.outputs.snap }} --clobber | ||
|
|
||
| - name: Publish snap to Snap Store | ||
| if: ${{ env.SNAPCRAFT_STORE_CREDENTIALS != '' && (github.event_name == 'release' || inputs.publish) }} | ||
| uses: snapcore/action-publish@v1 | ||
| with: | ||
| snap: ${{ steps.build.outputs.snap }} | ||
| release: ${{ steps.meta.outputs.channel }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| name: Winget | ||
|
|
||
| on: | ||
| release: | ||
| types: | ||
| - published | ||
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: Existing GitHub release tag like v0.0.102. | ||
| required: true | ||
| type: string | ||
| submit_update: | ||
| description: Submit a wingetcreate update PR. | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| generate-manifests: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| tag: ${{ steps.meta.outputs.tag }} | ||
| version: ${{ steps.meta.outputs.version }} | ||
| installer_url: ${{ steps.meta.outputs.installer_url }} | ||
| steps: | ||
| - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 | ||
|
|
||
| - name: Setup bun | ||
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 | ||
|
|
||
| - name: Resolve release metadata | ||
| id: meta | ||
| shell: bash | ||
| run: | | ||
| if [[ "${GITHUB_EVENT_NAME}" == "release" ]]; then | ||
| TAG="${{ github.event.release.tag_name }}" | ||
| else | ||
| TAG="${{ inputs.tag }}" | ||
| fi | ||
|
|
||
| VERSION="${TAG#v}" | ||
| INSTALLER_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/Dora_${VERSION}_x64_en-US.msi" | ||
| CHECKSUMS_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/checksums-windows.txt" | ||
|
|
||
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "installer_url=$INSTALLER_URL" >> "$GITHUB_OUTPUT" | ||
| echo "checksums_url=$CHECKSUMS_URL" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Download Windows checksums | ||
| run: curl --fail --location --output checksums-windows.txt "${{ steps.meta.outputs.checksums_url }}" | ||
|
|
||
| - name: Generate Winget manifests | ||
| run: | | ||
| bun run release:winget -- \ | ||
| --version=${{ steps.meta.outputs.version }} \ | ||
| --installer-url=${{ steps.meta.outputs.installer_url }} \ | ||
| --checksums-file=checksums-windows.txt \ | ||
| --installer-file=Dora_${{ steps.meta.outputs.version }}_x64_en-US.msi | ||
|
|
||
| - name: Archive Winget manifests | ||
| run: | | ||
| tar -czf winget-manifests-${{ steps.meta.outputs.version }}.tar.gz \ | ||
| -C packaging/winget/manifests/${{ steps.meta.outputs.version }} . | ||
|
|
||
| - name: Upload Winget manifest artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: winget-manifests-${{ steps.meta.outputs.version }} | ||
| path: winget-manifests-${{ steps.meta.outputs.version }}.tar.gz | ||
|
|
||
| - name: Upload Winget manifests to GitHub release | ||
| if: ${{ github.event_name == 'release' }} | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: gh release upload ${{ steps.meta.outputs.tag }} winget-manifests-${{ steps.meta.outputs.version }}.tar.gz --clobber | ||
|
|
||
| submit-update: | ||
| needs: generate-manifests | ||
| if: ${{ (github.event_name == 'release' && vars.WINGET_PACKAGE_READY == 'true') || (github.event_name == 'workflow_dispatch' && inputs.submit_update) }} | ||
| runs-on: windows-latest | ||
| env: | ||
| WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_CREATE_GITHUB_TOKEN }} | ||
| steps: | ||
| - name: Skip when Winget token is not configured | ||
| if: ${{ env.WINGET_CREATE_GITHUB_TOKEN == '' }} | ||
| shell: pwsh | ||
| run: | | ||
| Write-Host "WINGET_CREATE_GITHUB_TOKEN is not configured. Skipping automated Winget submission." | ||
| exit 0 | ||
|
|
||
| - name: Install WingetCreate dependencies | ||
| if: ${{ env.WINGET_CREATE_GITHUB_TOKEN != '' }} | ||
| shell: pwsh | ||
| run: | | ||
| Invoke-WebRequest https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx -OutFile Microsoft.VCLibs.x64.14.00.Desktop.appx | ||
| Add-AppxPackage .\Microsoft.VCLibs.x64.14.00.Desktop.appx | ||
| Invoke-WebRequest https://aka.ms/wingetcreate/latest/msixbundle -OutFile wingetcreate.msixbundle | ||
| Add-AppxPackage .\wingetcreate.msixbundle | ||
|
|
||
| - name: Submit Winget update | ||
| if: ${{ env.WINGET_CREATE_GITHUB_TOKEN != '' }} | ||
| shell: pwsh | ||
| run: | | ||
| wingetcreate update RemcoStoeten.Dora ` | ||
| -u "${{ needs.generate-manifests.outputs.installer_url }}" ` | ||
| -v "${{ needs.generate-manifests.outputs.version }}" ` | ||
| -t "${env:WINGET_CREATE_GITHUB_TOKEN}" ` | ||
| --submit | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| # One-Machine Packaging Playbook | ||
|
|
||
| This is the shortest path if you only have one main machine and need to use Docker or VMs for the ecosystem-specific steps. | ||
|
|
||
| ## VM bootstrap on Ubuntu | ||
|
|
||
| If you want the repo to manage the packaging VMs for you, start here: | ||
|
|
||
| ```bash | ||
| bash tools/scripts/vm-lab.sh | ||
| ``` | ||
|
|
||
| Or directly: | ||
|
|
||
| ```bash | ||
| bash tools/scripts/vm-lab.sh setup-host | ||
| bash tools/scripts/vm-lab.sh create ubuntu | ||
| bash tools/scripts/vm-lab.sh create arch | ||
| ``` | ||
|
|
||
| Details live in `docs/distribution/vm-lab.md`. | ||
|
|
||
| ## First milestone: create a real tagged release | ||
|
|
||
| Package-manager publishing should start only after a real tagged release exists | ||
| and its assets are visible on the GitHub release page. | ||
|
|
||
| From the main repo: | ||
|
|
||
| ```bash | ||
| git tag v0.1.0 | ||
| git push origin v0.1.0 | ||
| ``` | ||
|
|
||
| Then wait for the `Release` GitHub Actions workflow to finish. That workflow now uploads: | ||
|
|
||
| - release installers | ||
| - `checksums-linux.txt` | ||
| - `checksums-windows.txt` | ||
|
|
||
| Verify the release page first. If the release assets are missing, stop there and fix the release before touching Winget, AUR, or Snap. | ||
|
|
||
| ## Winget from a Windows VM | ||
|
|
||
| Use a Windows 11 VM because `wingetcreate` is Windows-native. You need this VM | ||
| for the first public package submission only. | ||
|
|
||
| ### In the VM | ||
|
|
||
| 1. Install GitHub CLI and sign in if needed. | ||
| 2. Install `wingetcreate`: | ||
|
|
||
| ```powershell | ||
| winget install wingetcreate | ||
| ``` | ||
|
|
||
| 3. Create the first package submission: | ||
|
|
||
| ```powershell | ||
| wingetcreate new "https://github.com/remcostoeten/dora/releases/download/v0.1.0/Dora_0.1.0_x64_en-US.msi" | ||
| ``` | ||
|
|
||
| 4. Review the detected metadata carefully. | ||
| 5. Let `wingetcreate` create the PR to `microsoft/winget-pkgs`. | ||
|
|
||
| ### On later releases | ||
|
|
||
| Use: | ||
|
|
||
| ```powershell | ||
| wingetcreate update RemcoStoeten.Dora --urls "https://github.com/remcostoeten/dora/releases/download/v0.1.1/Dora_0.1.1_x64_en-US.msi" | ||
| ``` | ||
|
|
||
| After the package exists in `microsoft/winget-pkgs`, you can stop doing that by | ||
| hand. Set `WINGET_CREATE_GITHUB_TOKEN` in GitHub Actions, add the repository | ||
| variable `WINGET_PACKAGE_READY=true`, and let `.github/workflows/winget.yml` | ||
| submit update PRs automatically from published releases. | ||
|
|
||
| ## AUR from Docker on your main machine | ||
|
|
||
| You do not need a full Arch VM just to validate the package. | ||
|
|
||
| ### Generate the package files | ||
|
|
||
| ```bash | ||
| bun run release:aur -- \ | ||
| --version=0.1.0 \ | ||
| --checksums-file=apps/desktop/src-tauri/target/release/bundle/checksums-linux.txt \ | ||
| --appimage-file=Dora_0.1.0_amd64.AppImage | ||
| ``` | ||
|
|
||
| ### Validate in Docker | ||
|
|
||
| ```bash | ||
| bash tools/scripts/test-aur-docker.sh | ||
| ``` | ||
|
|
||
| That spins up `archlinux:latest`, installs `base-devel`, and runs `makepkg` against `packaging/aur`. | ||
|
|
||
| ### Publish to the real AUR repo | ||
|
|
||
| 1. Create an AUR account at `aur.archlinux.org`. | ||
| 2. Add your SSH key there. | ||
| 3. Clone the AUR repo: | ||
|
|
||
| ```bash | ||
| git clone ssh://aur@aur.archlinux.org/dora-bin.git ~/code/dora-bin-aur | ||
| ``` | ||
|
|
||
| 4. Sync the generated files: | ||
|
|
||
| ```bash | ||
| bash tools/scripts/sync-aur-repo.sh ~/code/dora-bin-aur | ||
| ``` | ||
|
|
||
| 5. Commit and push: | ||
|
|
||
| ```bash | ||
| cd ~/code/dora-bin-aur | ||
| git add PKGBUILD .SRCINFO | ||
| git commit -m "Update dora-bin to 0.1.0" | ||
| git push | ||
| ``` | ||
|
|
||
| ## Snap from your main machine or GitHub Actions | ||
|
|
||
| Snap does not need a separate repo. | ||
|
|
||
| ### Local build path | ||
|
|
||
| If your machine is Ubuntu or another Linux system with Snap available: | ||
|
|
||
| ```bash | ||
| sudo snap install snapcraft --classic | ||
| sudo /snap/bin/snapcraft pack --destructive-mode | ||
| ``` | ||
|
|
||
| ### CI build path | ||
|
|
||
| The repo now has: | ||
|
|
||
| - `.github/workflows/snap.yml` | ||
| - `snap/snapcraft.yaml` | ||
|
|
||
| When a GitHub release is published, the workflow builds the `.snap`, uploads it | ||
| to the release, and publishes it to the Snap Store if the store credential | ||
| secret exists. Manual dispatch still works for artifact-only or test runs. | ||
|
|
||
| ### Store publish path | ||
|
|
||
| 1. Create or log into your Snapcraft account. | ||
| 2. Register the `dora` snap name. | ||
| 3. Export store credentials: | ||
|
|
||
| ```bash | ||
| snapcraft export-login --snaps=dora \ | ||
| --acls package_access,package_push,package_update,package_release \ | ||
| exported.txt | ||
| ``` | ||
|
|
||
| 4. Add the contents of `exported.txt` as the GitHub Actions secret | ||
| `SNAPCRAFT_STORE_CREDENTIALS`. | ||
| 5. Publish a GitHub release and let `.github/workflows/snap.yml` handle the | ||
| build and store upload. | ||
|
|
||
| ## Recommended order | ||
|
|
||
| 1. Make the tagged GitHub release actually publish assets. | ||
| 2. Submit Winget from a Windows VM. | ||
| 3. Validate and publish AUR from Docker plus your normal host shell. | ||
| 4. Register the Snap name and add `SNAPCRAFT_STORE_CREDENTIALS`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Interactive Release Guide | ||
|
|
||
| Run this from your normal shell, including `fish`: | ||
|
|
||
| ```bash | ||
| bash tools/scripts/release-guide.sh | ||
| ``` | ||
|
|
||
| The script gives you an interactive menu that: | ||
|
|
||
| - checks branch, tag, versions, dirty worktree, and GitHub auth | ||
| - generates a release notes draft from `CHANGELOG.md` | ||
| - creates the local tag when the tree is clean | ||
| - pushes the tag | ||
| - creates the GitHub release with the generated notes | ||
| - prints the next AUR command and the one-time bootstrap steps for Winget and | ||
| Snap if those channels are not configured yet | ||
|
|
||
| It intentionally refuses to create a tag while the worktree is dirty. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): The submit-update job always allocates a Windows runner even when the Winget token is missing.
Because the job always runs on
windows-latest, it still allocates a Windows runner even whenWINGET_CREATE_GITHUB_TOKENis empty and the first step exits immediately. Consider moving the token check into the job-levelif:(e.g. append&& secrets.WINGET_CREATE_GITHUB_TOKEN != '') so the job is entirely skipped when the token isn’t configured.Suggested implementation: