From 35f7b1ac8d814e38aa1ed464126f87d7887024a0 Mon Sep 17 00:00:00 2001 From: Drew Smirnoff Date: Sun, 3 May 2026 13:09:52 +0400 Subject: [PATCH] ci: add more workflows for issues (#1220) ## What? Adds a lot more workflows to help handle issues and PRs better ## Why? It is getting hard to triage issues and pull requests, this will likely help Signed-off-by: drew --- .github/ISSUE_TEMPLATE/bug_report.yml | 23 +++- .github/labeler-config.yml | 48 +++++++- .github/labels.yml | 140 +++++++++++++++++++++++ .github/pr-paths.yml | 121 ++++++++++++++++++++ .github/workflows/demo.yml | 10 +- .github/workflows/feature-popularity.yml | 63 ++++++++++ .github/workflows/label-sync.yml | 64 +++++++++++ .github/workflows/labeler-backfill.yml | 72 ++++++++++++ .github/workflows/labeler.yml | 6 +- .github/workflows/needs-response.yml | 45 ++++++++ .github/workflows/pr-labeler.yml | 23 ++++ .github/workflows/screenshots.yml | 11 +- .github/workflows/stale.yml | 37 ++++++ .github/workflows/sync-gomod2nix.yml | 12 +- .github/workflows/update-flake.yml | 12 +- renovate.json | 4 + 16 files changed, 681 insertions(+), 10 deletions(-) create mode 100644 .github/labels.yml create mode 100644 .github/pr-paths.yml create mode 100644 .github/workflows/feature-popularity.yml create mode 100644 .github/workflows/label-sync.yml create mode 100644 .github/workflows/labeler-backfill.yml create mode 100644 .github/workflows/needs-response.yml create mode 100644 .github/workflows/pr-labeler.yml create mode 100644 .github/workflows/stale.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e1834b8bf318c03531d320677c966dd6874f0031..26a865637d83e9524690dd68cf7d173fb0bda898 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -50,11 +50,32 @@ body: description: "Run `go version` to find out. Only relevant if the issue is related to Go/compilation." placeholder: "e.g. 1.22.0" - - type: input + - type: dropdown id: os attributes: label: OS + options: + - Linux + - macOS + - Windows + - Other + validations: + required: true + + - type: input + id: os-version + attributes: + label: OS version placeholder: "e.g. macOS 14, Ubuntu 24.04, Windows 11" + + - type: dropdown + id: arch + attributes: + label: Architecture + options: + - amd64 (x86_64) + - arm64 (aarch64 / Apple Silicon) + - Other / unsure validations: required: true diff --git a/.github/labeler-config.yml b/.github/labeler-config.yml index e3a4eec77fe336e6c33f45a576e0e45ed553e2af..561a36c5ea50105922993b620be4b2faca2333f2 100644 --- a/.github/labeler-config.yml +++ b/.github/labeler-config.yml @@ -1,6 +1,6 @@ -"bug": '\b([Bb]ug(s)?|[Ee]rror(s)?|[Ff]ix(es)?)\b' +"bug": '\b([Bb]ug(s)?|[Ff]ix(es)?)\b' -"enhancement": '\b([Ee]nhancement(s)?|[Ff]eature(s)?|[Ii]dea(s)?|[Ff]eat(s)?)\b' +"enhancement": '\b([Ff]eat(s)?)\b' "documentation": '\b([Dd]ocumentation|[Dd]ocs|[Rr]eadme)\b' @@ -13,3 +13,47 @@ "ci": '\b([Cc]i|[Cc]ontinuous integration|[Bb]uild|[Ww]orkflow)\b' "chore": '\b([Cc]hore|[Mm]aintenance|[Rr]efactor|[Cc]leanup)\b' + +"os/windows": '\b([Ww]indows|[Ww]in(10|11)|[Mm]icrosoft)\b' + +"os/linux": '\b([Ll]inux|[Uu]buntu|[Dd]ebian|[Ff]edora|[Aa]rch [Ll]inux|[Nn]ix[Oo][Ss]|[Pp]op!?_?[Oo][Ss])\b' + +"os/macos": '\b([Mm]ac[Oo][Ss]?|[Oo][Ss] ?[Xx]|[Dd]arwin|[Mm]acbook)\b' + +"arch/arm64": '\b(arm64|aarch64|[Aa]pple ?[Ss]ilicon|[Mm][1-4]( [Pp]ro| [Mm]ax| [Uu]ltra)?|[Mm]ac(book)? [Mm][1-4])\b' + +"arch/amd64": '\b(amd64|x86[_-]?64|x64|[Ii]ntel( [Mm]ac)?)\b' + +"area/tui": '\b([Tt][Uu][Ii]|[Vv]iew|[Bb]ubble[Tt]ea|[Ll]ipgloss|[Kk]eybind(ing)?s?|[Tt]erminal [Uu][Ii])\b' + +"area/fetcher": '\b([Ff]etcher|[Ii][Mm][Aa][Pp]|[Ii]dle|[Mm]ailbox|[Ss]earch|[Ss]ub-?address)\b' + +"area/sender": '\b([Ss]ender|[Ss][Mm][Tt][Pp]|[Ss]end(ing)? [Mm]ail|[Cc]ompose)\b' + +"area/oauth": '\b([Oo][Aa]uth2?|[Xx][Oo][Aa][Uu][Tt][Hh]2?|[Gg]oogle [Aa]uth|[Mm]icrosoft [Aa]uth|[Tt]oken [Rr]efresh)\b' + +"area/calendar": '\b([Cc]alendar|[Ii][Cc]al|[Cc]al[Dd][Aa][Vv]|[Ee]vent(s)?)\b' + +"area/notify": '\b([Nn]otif(y|ication)s?|[Tt]oast|[Dd]esktop [Nn]otif)\b' + +"area/pgp": '\b([Pp][Gg][Pp]|[Gg][Pp][Gg]|[Ee]ncrypt(ion)?|[Dd]ecrypt|[Ss]ign(ing)?|[Kk]ey ?ring)\b' + +"area/plugin": '\b([Pp]lugin(s)?)\b' + +"area/theme": '\b([Tt]heme(s)?|[Cc]olor ?scheme|[Ss]tyling)\b' + +"area/i18n": '\b([Ii]18n|[Ll]10n|[Ll]ocali[sz]ation|[Tt]ranslat(e|ion)|[Ll]anguage [Pp]ack)\b' + +"area/config": '\b([Cc]onfig(uration)?|[Ss]ettings|[Cc]onfig\.yaml|[Cc]onfig\.toml|[Pp]references)\b' + +"area/cli": '\b([Cc][Ll][Ii]|[Cc]ommand[- ]?line|[Ff]lag(s)?|[Aa]rgument(s)?)\b' + +"area/daemon": '\b([Dd]aemon|[Rr][Pp][Cc]|[Bb]ackground [Ss]ervice|[Ss]ystemd)\b' + +"area/scard": '\b([Ss]mart ?card|[Ss]card|[Pp][Kk][Cc][Ss]#?11|[Yy]ubikey|[Hh]ardware [Tt]oken)\b' + +"area/nix": '\b([Nn]ix|[Nn]ix[Oo][Ss]|[Ff]lake|[Gg]omod2nix|[Hh]ome ?[Mm]anager)\b' + +"area/build": '\b([Bb]uild|[Mm]akefile|[Gg]oreleaser|[Ss]napcraft|[Ff]latpak|[Hh]omebrew|[Pp]ackag(e|ing))\b' + +"area/docs": '\b([Dd]ocumentation|[Dd]ocs|[Rr]eadme|[Mm]an ?page)\b' diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000000000000000000000000000000000000..fe60da30ca992ee016e6392eec60228fad90a0e7 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,140 @@ +# Label definitions. Synced by .github/workflows/label-sync.yml via `gh label`. + +# --- Type --- +- name: bug + color: d73a4a + description: Something isn't working +- name: enhancement + color: a2eeef + description: New feature or request +- name: documentation + color: 0075ca + description: Documentation changes +- name: question + color: d876e3 + description: Further information requested +- name: performance + color: fbca04 + description: Performance improvement +- name: dependencies + color: 0366d6 + description: Dependency updates +- name: ci + color: 1d76db + description: CI / build pipeline +- name: chore + color: cfd3d7 + description: Maintenance, refactor, cleanup +- name: security + color: b60205 + description: Security-related + +# --- Triage / lifecycle --- +- name: needs-triage + color: ededed + description: Awaiting maintainer review +- name: needs-response + color: fbca04 + description: Waiting on issue author reply +- name: stale + color: cccccc + description: No activity for extended period +- name: pinned + color: 0e8a16 + description: Exempt from stale +- name: in-progress + color: 5319e7 + description: Actively being worked on +- name: blocked + color: b60205 + description: Blocked on external dependency +- name: help-wanted + color: 008672 + description: Extra attention is needed +- name: good-first-issue + color: 7057ff + description: Good for newcomers +- name: popular + color: ff6f00 + description: High community interest (10+ 👍) +- name: duplicate + color: cfd3d7 + description: Duplicate of another issue +- name: wontfix + color: ffffff + description: Will not be worked on +- name: invalid + color: e4e669 + description: Not valid + +# --- OS --- +- name: os/windows + color: 0078d4 + description: Windows-specific +- name: os/linux + color: fcc624 + description: Linux-specific +- name: os/macos + color: 333333 + description: macOS-specific + +# --- Arch --- +- name: arch/arm64 + color: 6e40c9 + description: arm64 / aarch64 +- name: arch/amd64 + color: 1f6feb + description: amd64 / x86_64 + +# --- Area --- +- name: area/tui + color: c2e0c6 + description: Terminal UI / view layer +- name: area/fetcher + color: c2e0c6 + description: IMAP fetch / IDLE / search +- name: area/sender + color: c2e0c6 + description: SMTP send path +- name: area/oauth + color: c2e0c6 + description: OAuth / XOAUTH2 / auth flows +- name: area/calendar + color: c2e0c6 + description: Calendar integration +- name: area/notify + color: c2e0c6 + description: Notifications +- name: area/pgp + color: c2e0c6 + description: PGP / encryption +- name: area/plugin + color: c2e0c6 + description: Plugin system +- name: area/theme + color: c2e0c6 + description: Theming / colors +- name: area/i18n + color: c2e0c6 + description: Localization / translations +- name: area/config + color: c2e0c6 + description: Configuration / settings +- name: area/cli + color: c2e0c6 + description: CLI flags / commands +- name: area/daemon + color: c2e0c6 + description: Daemon / RPC +- name: area/scard + color: c2e0c6 + description: Smart card / PKCS#11 +- name: area/nix + color: c2e0c6 + description: Nix flake / packaging +- name: area/build + color: c2e0c6 + description: Build system / Makefile / packaging +- name: area/docs + color: c2e0c6 + description: Docs site / README diff --git a/.github/pr-paths.yml b/.github/pr-paths.yml new file mode 100644 index 0000000000000000000000000000000000000000..2fabf3bafce7bbdd8b3264162a121f406a30e407 --- /dev/null +++ b/.github/pr-paths.yml @@ -0,0 +1,121 @@ +# Path → label rules for actions/labeler@v5 (PR file paths). + +"area/tui": + - changed-files: + - any-glob-to-any-file: + - tui/** + - view/** + +"area/fetcher": + - changed-files: + - any-glob-to-any-file: + - fetcher/** + +"area/sender": + - changed-files: + - any-glob-to-any-file: + - sender/** + +"area/oauth": + - changed-files: + - any-glob-to-any-file: + - fetcher/xoauth2.go + - "**/oauth*" + - "**/xoauth*" + +"area/calendar": + - changed-files: + - any-glob-to-any-file: + - calendar/** + +"area/notify": + - changed-files: + - any-glob-to-any-file: + - notify/** + +"area/pgp": + - changed-files: + - any-glob-to-any-file: + - pgp/** + +"area/plugin": + - changed-files: + - any-glob-to-any-file: + - plugin/** + - plugins/** + +"area/theme": + - changed-files: + - any-glob-to-any-file: + - theme/** + +"area/i18n": + - changed-files: + - any-glob-to-any-file: + - i18n/** + +"area/config": + - changed-files: + - any-glob-to-any-file: + - config/** + +"area/cli": + - changed-files: + - any-glob-to-any-file: + - cli/** + +"area/daemon": + - changed-files: + - any-glob-to-any-file: + - daemon/** + - daemonclient/** + - daemonrpc/** + +"area/scard": + - changed-files: + - any-glob-to-any-file: + - pgp/yubikey.go + - "**/scard*" + - "**/pkcs11*" + +"area/nix": + - changed-files: + - any-glob-to-any-file: + - flake.nix + - flake.lock + - gomod2nix.toml + +"area/build": + - changed-files: + - any-glob-to-any-file: + - Makefile + - dist/** + - snapcraft.yaml + - com.floatpane.matcha.yaml + - .goreleaser* + - clib/** + +"area/docs": + - changed-files: + - any-glob-to-any-file: + - docs/** + - README.md + - "**/*.md" + +"ci": + - changed-files: + - any-glob-to-any-file: + - .github/workflows/** + - .github/labeler-config.yml + - .github/labels.yml + - .github/pr-paths.yml + +"dependencies": + - changed-files: + - any-glob-to-any-file: + - go.mod + - go.sum + - package.json + - package-lock.json + - docs/package.json + - docs/package-lock.json diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml index 1a024e827bf3157fb9205c67854a41eaf311a777..472a5e0c32fbc5ace93e59884af2e9afce1fe813 100644 --- a/.github/workflows/demo.yml +++ b/.github/workflows/demo.yml @@ -87,8 +87,14 @@ jobs: commit-message: "docs: update demo.gif from release" title: "docs: update demo.gif" body: | - This PR updates the demo GIF based on the latest release version. - Generated automatically by the Update Demo VHS workflow. + ## What? + + Replaces `public/assets/demo.gif` with a freshly recorded VHS run. + + ## Why? + + Keeps the demo GIF aligned with the latest release so README and docs reflect current behaviour. Generated automatically by the Update Demo VHS workflow. branch: "update-demo-gif" base: "master" add-paths: public/assets/demo.gif + labels: documentation diff --git a/.github/workflows/feature-popularity.yml b/.github/workflows/feature-popularity.yml new file mode 100644 index 0000000000000000000000000000000000000000..2b7025c96d81f7d0766c545257c4f99725b81f17 --- /dev/null +++ b/.github/workflows/feature-popularity.yml @@ -0,0 +1,63 @@ +name: "Feature Request Triage" + +on: + schedule: + - cron: "0 3 * * 1" + issues: + types: [opened, labeled] + workflow_dispatch: + +permissions: + issues: write + +jobs: + welcome: + if: github.event_name == 'issues' && github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'enhancement') + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + body: [ + "Thanks for the suggestion!", + "", + "If you want to see this feature land, give the original post a 👍. Maintainers prioritize feature requests by reaction count.", + "Comment to add detail or use cases — extra context helps triage." + ].join("\n") + }); + + promote-popular: + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + script: | + const threshold = 10; + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'enhancement', + per_page: 100 + }); + for (const issue of issues) { + if (issue.pull_request) continue; + if (issue.labels.some(l => (l.name || l) === 'popular')) continue; + const upvotes = (issue.reactions && issue.reactions['+1']) || 0; + if (upvotes >= threshold) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: ['popular'] + }); + core.info(`labeled #${issue.number} popular (${upvotes} 👍)`); + } + } diff --git a/.github/workflows/label-sync.yml b/.github/workflows/label-sync.yml new file mode 100644 index 0000000000000000000000000000000000000000..e630e45de8da030da78577143b69bc8a6f697bbd --- /dev/null +++ b/.github/workflows/label-sync.yml @@ -0,0 +1,64 @@ +name: "Label Sync" + +on: + push: + branches: [master] + paths: + - .github/labels.yml + - .github/workflows/label-sync.yml + workflow_dispatch: + inputs: + prune: + description: "Delete labels not in labels.yml" + type: boolean + default: false + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + LABELS_FILE: .github/labels.yml + PRUNE: ${{ github.event.inputs.prune || 'false' }} + steps: + - uses: actions/checkout@v6 + + - name: Upsert labels + run: | + set -euo pipefail + count=$(yq '. | length' "$LABELS_FILE") + for i in $(seq 0 $((count - 1))); do + name=$(yq ".[$i].name" "$LABELS_FILE") + color=$(yq ".[$i].color" "$LABELS_FILE") + description=$(yq ".[$i].description // \"\"" "$LABELS_FILE") + echo "::group::$name" + gh label create "$name" \ + --repo "$GITHUB_REPOSITORY" \ + --color "$color" \ + --description "$description" \ + --force + echo "::endgroup::" + done + + - name: Prune extra labels + if: env.PRUNE == 'true' + run: | + set -euo pipefail + desired=$(yq -r '.[].name' "$LABELS_FILE" | sort -u) + current=$(gh label list --repo "$GITHUB_REPOSITORY" --limit 500 --json name -q '.[].name' | sort -u) + extras=$(comm -23 <(echo "$current") <(echo "$desired")) + if [ -z "$extras" ]; then + echo "No extra labels." + exit 0 + fi + echo "Deleting:" + echo "$extras" + while IFS= read -r name; do + [ -z "$name" ] && continue + gh label delete "$name" --repo "$GITHUB_REPOSITORY" --yes + done <<< "$extras" diff --git a/.github/workflows/labeler-backfill.yml b/.github/workflows/labeler-backfill.yml new file mode 100644 index 0000000000000000000000000000000000000000..590217902162e37ff1140ae3121e46b8e62e901f --- /dev/null +++ b/.github/workflows/labeler-backfill.yml @@ -0,0 +1,72 @@ +name: "Labeler Backfill" + +on: + workflow_dispatch: + inputs: + target: + description: "What to backfill" + type: choice + default: both + options: + - issues + - prs + - both + +permissions: + issues: write + pull-requests: write + contents: read + +jobs: + issues: + if: github.event.inputs.target == 'issues' || github.event.inputs.target == 'both' + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + steps: + - name: Re-trigger issue labeler via no-op edit + run: | + set -euo pipefail + mapfile -t numbers < <(gh issue list --repo "$GITHUB_REPOSITORY" --state open --limit 1000 --json number -q '.[].number') + for n in "${numbers[@]}"; do + body=$(gh issue view "$n" --repo "$GITHUB_REPOSITORY" --json body -q .body) + # PATCH with same body → fires `edited` → labeler.yml runs + gh api -X PATCH "repos/$GITHUB_REPOSITORY/issues/$n" -f body="$body" >/dev/null + echo "touched #$n" + sleep 1 + done + + prs: + if: github.event.inputs.target == 'prs' || github.event.inputs.target == 'both' + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v6 + + - name: Collect open PR numbers + id: prs + run: | + nums=$(gh pr list --repo "$GITHUB_REPOSITORY" --state open --limit 1000 --json number -q '[.[].number] | join(",")') + echo "list=$nums" >> "$GITHUB_OUTPUT" + + - name: Path labeler on open PRs + if: steps.prs.outputs.list != '' + uses: actions/labeler@v5 + with: + repo-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + configuration-path: .github/pr-paths.yml + sync-labels: false + dot: true + pr-number: ${{ steps.prs.outputs.list }} + + - name: Re-trigger text labeler on PRs via no-op edit + run: | + set -euo pipefail + mapfile -t numbers < <(gh pr list --repo "$GITHUB_REPOSITORY" --state open --limit 1000 --json number -q '.[].number') + for n in "${numbers[@]}"; do + body=$(gh pr view "$n" --repo "$GITHUB_REPOSITORY" --json body -q .body) + gh api -X PATCH "repos/$GITHUB_REPOSITORY/pulls/$n" -f body="$body" >/dev/null + echo "touched PR #$n" + sleep 1 + done diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 2d84388d245722189838a33dae87654386bc1eca..136af89d4ce0435b8a896ba0ab97cfa51d20e023 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -8,6 +8,10 @@ on: jobs: triage: + if: > + ${{ github.event_name == 'issues' + || (!startsWith(github.event.pull_request.title, 'chore(deps):') + && !contains(fromJSON('["chore/sync-gomod2nix","chore/update-flake-lock","update-screenshots","update-demo-gif"]'), github.head_ref)) }} permissions: contents: read issues: write @@ -19,7 +23,7 @@ jobs: - name: Apply Labels uses: github/issue-labeler@v3.4 with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" + repo-token: "${{ secrets.HOMEBREW_GITHUB_TOKEN }}" configuration-path: .github/labeler-config.yml enable-versioned-regex: 0 include-title: 1 diff --git a/.github/workflows/needs-response.yml b/.github/workflows/needs-response.yml new file mode 100644 index 0000000000000000000000000000000000000000..c1cd71cb6b6d6d1f3a1b9325a64578dc18722448 --- /dev/null +++ b/.github/workflows/needs-response.yml @@ -0,0 +1,45 @@ +name: "Needs Response" + +on: + issue_comment: + types: [created] + +permissions: + issues: write + +jobs: + toggle-label: + if: github.event.issue.pull_request == null + runs-on: ubuntu-latest + steps: + - name: Add needs-response when maintainer comments + if: > + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) && + github.event.comment.user.login != github.event.issue.user.login + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + script: | + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: ['needs-response'] + }); + + - name: Remove needs-response when issue author replies + if: github.event.comment.user.login == github.event.issue.user.login + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + script: | + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + name: 'needs-response' + }); + } catch (e) { + if (e.status !== 404) throw e; + } diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 0000000000000000000000000000000000000000..c5b4237cd0f3c3f12f254acbf13199686bfb9338 --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,23 @@ +name: "PR Path Labeler" + +on: + pull_request_target: + types: [opened, synchronize, reopened, ready_for_review] + +permissions: + contents: read + pull-requests: write + +jobs: + label: + if: > + ${{ !startsWith(github.event.pull_request.title, 'chore(deps):') + && !contains(fromJSON('["chore/sync-gomod2nix","chore/update-flake-lock","update-screenshots","update-demo-gif"]'), github.head_ref) }} + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v5 + with: + repo-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + configuration-path: .github/pr-paths.yml + sync-labels: false + dot: true diff --git a/.github/workflows/screenshots.yml b/.github/workflows/screenshots.yml index aa56b940896e4d5870f547675e05f9f49b82b8cd..977f6eef1781b8472c24c9c99e7a774adfd8bcf5 100644 --- a/.github/workflows/screenshots.yml +++ b/.github/workflows/screenshots.yml @@ -124,9 +124,9 @@ jobs: - name: Generate PR Body id: pr-body run: | - BODY="This PR updates the feature screenshots based on the latest release version. + BODY="## What? - Generated automatically by the Generate Screenshots workflow. + Refreshes the feature screenshots in \`docs/docs/assets/features/\`. ### Screenshots included:" @@ -137,6 +137,12 @@ jobs: - \`$filename\`" done + BODY="$BODY + + ## Why? + + Keeps documentation visuals aligned with the current TUI. Generated automatically by the Generate Screenshots workflow on the latest release." + echo "body<> $GITHUB_OUTPUT echo "$BODY" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT @@ -151,3 +157,4 @@ jobs: branch: "update-screenshots" base: "master" add-paths: docs/docs/assets/features/ + labels: documentation diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000000000000000000000000000000000..4110eee0f218bb47cd09c7fadb20325516bf9065 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,37 @@ +name: "Stale issues and PRs" + +on: + schedule: + - cron: "0 2 * * *" + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }} + days-before-issue-stale: 30 + days-before-issue-close: 14 + days-before-pr-stale: 45 + days-before-pr-close: 21 + stale-issue-label: "stale" + stale-pr-label: "stale" + exempt-issue-labels: "pinned,security,help-wanted,good-first-issue,in-progress" + exempt-pr-labels: "pinned,security,in-progress,blocked" + stale-issue-message: > + This issue has had no activity for 30 days. It will be closed in 14 days unless updated. + Add a comment or remove the `stale` label to keep it open. + stale-pr-message: > + This PR has had no activity for 45 days. It will be closed in 21 days unless updated. + close-issue-message: > + Closing due to inactivity. Reopen if still relevant. + close-pr-message: > + Closing due to inactivity. Reopen if still relevant. + remove-stale-when-updated: true + operations-per-run: 100 diff --git a/.github/workflows/sync-gomod2nix.yml b/.github/workflows/sync-gomod2nix.yml index 8152df3f848f443f01177967254b92444bdca24f..0815ab11f0784925781a86658f9aa140985f78eb 100644 --- a/.github/workflows/sync-gomod2nix.yml +++ b/.github/workflows/sync-gomod2nix.yml @@ -39,5 +39,15 @@ jobs: git commit -m "chore: sync gomod2nix.toml" git push -f origin "$BRANCH" if ! gh pr list --head "$BRANCH" --state open | grep -q .; then - gh pr create --title "chore: sync gomod2nix.toml" --body "Automated gomod2nix.toml sync after Go dependency changes." --base master + BODY=$(cat <<'EOF' + ## What? + + Regenerates `gomod2nix.toml` to reflect the current `go.mod` / `go.sum`. + + ## Why? + + Keeps the Nix build in sync with Go module changes. Without this, `nix build` fails when new or upgraded Go deps are missing from `gomod2nix.toml`. Generated automatically by the gomod2nix sync workflow. + EOF + ) + gh pr create --title "chore: sync gomod2nix.toml" --body "$BODY" --base master --label chore --label area/nix fi diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 06473719e288983d7733532d9d4fc04db09d994c..577d06fb8f7eb5c39839106b1b79afd3c4efce43 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -34,5 +34,15 @@ jobs: git commit -m "chore: update flake.lock" git push -f origin "$BRANCH" if ! gh pr list --head "$BRANCH" --state open | grep -q .; then - gh pr create --title "chore: update flake.lock" --body "Automated flake.lock update." --base master + BODY=$(cat <<'EOF' + ## What? + + Updates `flake.lock` to the latest revisions of all flake inputs (`nixpkgs`, `flake-utils`, etc.). + + ## Why? + + Keeps Nix inputs current so contributors and CI build against fresh `nixpkgs`. Picks up upstream security and toolchain fixes. Generated automatically by the flake-lock update workflow on changes to `go.sum`. + EOF + ) + gh pr create --title "chore: update flake.lock" --body "$BODY" --base master --label chore --label area/nix fi diff --git a/renovate.json b/renovate.json index 9ead3aa2008dfe1632ece9db28258e950c725c6a..f928fe584200ebbb30dcce4f6fffa0d6c0998b20 100644 --- a/renovate.json +++ b/renovate.json @@ -2,6 +2,10 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"], "postUpdateOptions": ["gomodTidy"], + "labels": ["dependencies"], + "commitMessage": "chore(deps): {{depName}} ^ {{newVersion}}", + "prTitle": "chore(deps): {{depName}} ^ {{newVersion}}", + "prBodyTemplate": "## What?\n\n{{{table}}}{{{notes}}}{{{changelogs}}}\n\n## Why?\n\nAutomated dependency update via Renovate.\n\n{{{configDescription}}}\n\n{{{warnings}}}\n\n---\n\n{{{controls}}}\n\n{{{footer}}}", "packageRules": [ { "matchManagers": ["gomod"],