From 928ee8ebaa877f2aa6329c1fc44bdf11e01eed3d Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Tue, 27 Oct 2026 06:14:00 -0700 Subject: [PATCH] ci(github): build and attach artifacts for macOS and Windows One workflow builds both platforms and publishes what they built. macOS builds and checks through nix on the self-hosted runner; Windows builds natively on `windows-latest` for x86_64 and aarch64, with fmt, clippy and the tests on x86_64. A publish job packages the executables and checksums and writes the release notes with kokai: a `v*` tag makes a release, a scheduled or manual run on master replaces the rolling nightly, and any other push to master makes a draft. There is no nix on the Windows runner, so it checks out the komorebi sources at the revisions `flake.lock` pins. --- .github/dependabot.yml | 21 ++++ .github/pull_request_template.md | 7 ++ .github/workflows/ci.yaml | 204 +++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yaml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..48cb2675 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + assignees: + - "LGUG2Z" + commit-message: + prefix: chore + include: scope + + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + assignees: + - "LGUG2Z" + commit-message: + prefix: chore + include: scope diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..5059bfde --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ + diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..5f5b5249 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,204 @@ +# Adapted from komorebi's windows workflow, with a macOS job added. One workflow builds both +# platforms and one job publishes what they built. + +name: ci + +on: + pull_request: + branches: + - "*" + push: + branches: + - master + - feature/* + - hotfix/* + tags: + - v* + schedule: + - cron: "30 0 * * 0" # Every Sunday at 00:30 UTC + workflow_dispatch: + +jobs: + cargo-deny: + if: github.repository == 'LGUG2Z/komorebi-recorder' + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - uses: EmbarkStudios/cargo-deny-action@v2 + + # `nix flake check` includes the Windows clippy check, which type-checks every `cfg(windows)` line + macos: + if: github.repository == 'LGUG2Z/komorebi-recorder' + runs-on: self-hosted + permissions: write-all + env: + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - run: nix flake check + - run: nix build + - uses: actions/upload-artifact@v7 + with: + name: komorebi-recorder-aarch64-apple-darwin-${{ github.sha }} + path: result/bin/komorebi-recorder + retention-days: 14 + + windows: + if: github.repository == 'LGUG2Z/komorebi-recorder' + strategy: + fail-fast: true + matrix: + platform: + - os-name: Windows-x86_64 + runs-on: windows-latest + target: x86_64-pc-windows-msvc + - os-name: Windows-aarch64 + runs-on: windows-latest + target: aarch64-pc-windows-msvc + runs-on: ${{ matrix.platform.runs-on }} + permissions: write-all + env: + RUSTFLAGS: -Ctarget-feature=+crt-static -Dwarnings + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + # There is no nix here, so the komorebi sources the recorder indexes (and its tests read) are + # checked out at the revisions flake.lock pins, which stays the single place they are pinned + - name: Check out the komorebi sources at the revisions flake.lock pins + shell: bash + run: | + for input in komorebi-mac:LGUG2Z/komorebi-for-mac komorebi-windows:LGUG2Z/komorebi; do + name="${input%%:*}" + repository="${input#*:}" + rev="$(jq -r ".nodes[\"$name\"].locked.rev" flake.lock)" + directory="$RUNNER_TEMP/$name" + git init --quiet "$directory" + git -C "$directory" fetch --quiet --depth 100 "https://github.com/$repository" "$rev" + git -C "$directory" checkout --quiet FETCH_HEAD + variable="$(echo "$name" | sed -e 's/^komorebi-mac$/KOMOREBI_MAC/' -e 's/^komorebi-windows$/KOMOREBI_WINDOWS/')" + echo "${variable}_SRC=$(cygpath -m "$directory")" >> "$GITHUB_ENV" + echo "${variable}_COMMIT=$rev" >> "$GITHUB_ENV" + done + - run: rustup toolchain install stable --profile minimal + - run: rustup component add --toolchain stable-x86_64-pc-windows-msvc clippy + - run: rustup toolchain install nightly --allow-downgrade -c rustfmt + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: "true" + cache-all-crates: "true" + key: ${{ matrix.platform.target }} + # the checks run on the x86_64 host, once + - if: matrix.platform.target == 'x86_64-pc-windows-msvc' + run: cargo +nightly fmt --check + - if: matrix.platform.target == 'x86_64-pc-windows-msvc' + run: cargo clippy --workspace --all-targets --locked -- -D warnings + # Informational until it has been seen green on Windows: the tests were written on a Mac and + # nothing has run them here. Make it blocking by removing `continue-on-error`. + - if: matrix.platform.target == 'x86_64-pc-windows-msvc' + run: cargo test --workspace --locked + continue-on-error: true + - uses: houseabsolute/actions-rust-cross@v1 + with: + command: "build" + target: ${{ matrix.platform.target }} + args: "--locked --release" + - uses: actions/upload-artifact@v7 + with: + name: komorebi-recorder-${{ matrix.platform.target }}-${{ github.sha }} + path: | + target/${{ matrix.platform.target }}/release/*.exe + target/${{ matrix.platform.target }}/release/*.pdb + retention-days: 14 + + # Packages what the two builds made and publishes it. What kind of publication depends on the + # event: a push of a `v*` tag releases; a scheduled or manual run on master replaces the rolling + # `nightly` prerelease; any other push to master makes a draft release to look at. + publish: + if: github.repository == 'LGUG2Z/komorebi-recorder' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) + needs: [macos, windows] + runs-on: self-hosted + permissions: write-all + env: + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Decide what is being published + shell: bash + run: | + if [[ "$GITHUB_REF" == refs/tags/v* ]]; then + echo "MODE=release" >> "$GITHUB_ENV" + echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV" + elif [[ "$GITHUB_EVENT_NAME" == schedule || "$GITHUB_EVENT_NAME" == workflow_dispatch ]]; then + echo "MODE=nightly" >> "$GITHUB_ENV" + echo "VERSION=nightly" >> "$GITHUB_ENV" + else + echo "MODE=draft" >> "$GITHUB_ENV" + echo "VERSION=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n 1)" >> "$GITHUB_ENV" + fi + - uses: actions/download-artifact@v8 + - name: Package + shell: bash + run: | + mkdir dist + # artifacts do not keep the executable bit + chmod +x "komorebi-recorder-aarch64-apple-darwin-${GITHUB_SHA}/komorebi-recorder" + zip -j "dist/komorebi-recorder-${VERSION}-aarch64-apple-darwin.zip" \ + "komorebi-recorder-aarch64-apple-darwin-${GITHUB_SHA}/komorebi-recorder" + for triple in x86_64-pc-windows-msvc aarch64-pc-windows-msvc; do + zip -j "dist/komorebi-recorder-${VERSION}-${triple}.zip" \ + "komorebi-recorder-${triple}-${GITHUB_SHA}/${triple}/release/"*.exe + done + (cd dist && shasum -a 256 -- * > checksums.txt) + - name: Write the release notes + shell: bash + run: | + if ! type kokai >/dev/null; then cargo install --locked kokai --force; fi + case "$MODE" in + nightly) + git tag -d nightly || true + git tag nightly + ref=nightly ;; + draft) ref="$GITHUB_REF_NAME" ;; + release) ref="$GITHUB_REF_NAME" ;; + esac + kokai release --no-emoji --add-links github:commits,issues --ref "$ref" > "$RUNNER_TEMP/release-notes.md" + - name: Publish + shell: bash + run: | + case "$MODE" in + nightly) + gh release delete nightly --yes || true + git push origin :nightly || true + gh release create nightly \ + --target "$GITHUB_SHA" \ + --prerelease \ + --title "komorebi-recorder nightly (${GITHUB_SHA})" \ + --notes-file "$RUNNER_TEMP/release-notes.md" \ + dist/* ;; + draft) + # a draft is not found by its tag, so the previous one is found in the list + gh api "repos/${GITHUB_REPOSITORY}/releases" --paginate \ + --jq '.[] | select(.draft and .tag_name == "draft") | .id' | + while read -r id; do gh api -X DELETE "repos/${GITHUB_REPOSITORY}/releases/${id}"; done + gh release create draft \ + --draft \ + --target "$GITHUB_SHA" \ + --title "komorebi-recorder ${VERSION} (draft, ${GITHUB_SHA})" \ + --notes-file "$RUNNER_TEMP/release-notes.md" \ + dist/* ;; + release) + gh release create "$GITHUB_REF_NAME" \ + --verify-tag \ + --title "komorebi-recorder ${VERSION}" \ + --notes-file "$RUNNER_TEMP/release-notes.md" \ + dist/* ;; + esac +