diff --git a/.github/workflows/app-build-verify.yml b/.github/workflows/app-build-verify.yml index f0c5e15..bba0afd 100644 --- a/.github/workflows/app-build-verify.yml +++ b/.github/workflows/app-build-verify.yml @@ -285,7 +285,7 @@ jobs: startsWith(inputs.runner-os, 'ubuntu') && contains(fromJSON('["", "Linux"]'), inputs.target-platform) && contains(fromJSON('["", "system", "appimage"]'), inputs.target-format) - uses: docker/login-action@v4.1.0 + uses: docker/login-action@v4.2.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -296,7 +296,7 @@ jobs: startsWith(inputs.runner-os, 'ubuntu') && contains(fromJSON('["", "Linux"]'), inputs.target-platform) && contains(fromJSON('["", "system", "appimage"]'), inputs.target-format) - uses: docker/setup-buildx-action@v4.0.0 + uses: docker/setup-buildx-action@v4.1.0 - name: Docker Caching Configuration id: docker diff --git a/.github/workflows/app-create-verify.yml b/.github/workflows/app-create-verify.yml index 2a51e98..c013b56 100644 --- a/.github/workflows/app-create-verify.yml +++ b/.github/workflows/app-create-verify.yml @@ -87,9 +87,11 @@ jobs: **/pyproject.toml .pre-commit-config.yaml + - name: Update pip + run: python -m pip install -U pip + - name: Install Dependencies - # must install before Briefcase below since requirements.txt contains an entry for Briefcase - run: python -m pip install -Ur ./briefcase-template/requirements.txt + run: python -m pip install --group './briefcase-template/pyproject.toml:create-verify' - name: Get Briefcase Package # Briefcase will build and package itself in a previous step in its CI diff --git a/.github/workflows/check-pr-template.yml b/.github/workflows/check-pr-template.yml new file mode 100644 index 0000000..9196bac --- /dev/null +++ b/.github/workflows/check-pr-template.yml @@ -0,0 +1,10 @@ +name: PR Checklist + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + +jobs: + check-pr-template: + name: Check PR template + uses: beeware/.github/.github/workflows/pr-checklist.yml@main diff --git a/.github/workflows/coc-update.yml b/.github/workflows/coc-update.yml index e23e231..43f34a6 100644 --- a/.github/workflows/coc-update.yml +++ b/.github/workflows/coc-update.yml @@ -65,7 +65,7 @@ jobs: working-directory: ./targetrepo run: | git config --local user.email "brutus@beeware.org" - git config --local user.name "Brutus (robot)" + git config --local user.name "Brutus[bot]" - name: Replace Code of Conduct working-directory: ./targetrepo run: | diff --git a/.github/workflows/dependabot-changenote.yml b/.github/workflows/dependabot-changenote.yml index a39ba59..24c8bef 100644 --- a/.github/workflows/dependabot-changenote.yml +++ b/.github/workflows/dependabot-changenote.yml @@ -42,7 +42,8 @@ jobs: CHANGENOTE_FILEPATH="./changes/${PR_NUM}.misc.${{ inputs.changenote-format }}" # Create change note from first line of dependabot commit - NEWS=$(printf "%s" "${{ github.event.head_commit.message }}" | head -n1 | sed -e 's/Bump/Updated/') + # Replace "Bump" with "Updated", and add markup to URLs. + NEWS=$(printf "%s" "${{ github.event.head_commit.message }}" | head -n1 | sed -e 's|Bump|Updated|' | sed -e 's|\(https://[^/]*/[^ .]*\)|<\1>|') printf "%s.\n" "${NEWS}" > "${CHANGENOTE_FILEPATH}" # Commit the change note diff --git a/.github/workflows/new-issue.yml b/.github/workflows/new-issue.yml new file mode 100644 index 0000000..e4a99c0 --- /dev/null +++ b/.github/workflows/new-issue.yml @@ -0,0 +1,18 @@ +name: New issue + +on: + issues: + types: + - opened + - reopened + - transferred + +jobs: + add-to-project: + name: Add issue to BeeWare project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v2.0.0 + with: + project-url: https://github.com/orgs/beeware/projects/1 + github-token: ${{ secrets.BRUTUS_PAT_TOKEN }} diff --git a/.github/workflows/pr-checklist.yml b/.github/workflows/pr-checklist.yml new file mode 100644 index 0000000..f535130 --- /dev/null +++ b/.github/workflows/pr-checklist.yml @@ -0,0 +1,45 @@ +name: PR Checklist + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + workflow_call: + +jobs: + check-pr-template: + name: Check PR template + runs-on: ubuntu-latest + if: github.event.pull_request.user.login != 'dependabot[bot]' && github.event.pull_request.user.login != 'Brutus[bot]' + steps: + - name: Check PR body + env: + PR_BODY: ${{ github.event.pull_request.body }} + run: | + require() { + if ! grep -qE -- "$1" <<< "$PR_BODY"; then + echo "::error::$2" + exit 1 + fi + } + + require "^[[:space:]]*## PR Checklist:" \ + "Could not find the BeeWare PR checklist in the pull request comment. This probably means you've used a tool to submit your PR, rather than the GitHub UI. The BeeWare project provides and requires the use of a standard template for all PRs. Your PR will be ignored until/unless you add the required components of the template. See https://beeware.org/contributing/guide/how/submit-pr/#pr-content for details." + + require "^[[:space:]]*- \[\s*[xX]\s*\] I will abide by the BeeWare Code of Conduct" \ + "The 'Code of Conduct' checkbox in the PR checklist must be checked." + + require "^[[:space:]]*- \[\s*[xX]\s*\] I have read and have followed the \*\*CONTRIBUTING.md\*\* file" \ + "The 'CONTRIBUTING.md' checkbox in the PR checklist must be checked." + + if grep -qE -- "^[[:space:]]*- \[\s*[xX]\s*\] This PR was generated or assisted using an AI tool" <<< "$PR_BODY"; then + require "^[[:space:]]*(-\s+)?Assisted-by:" "'Assisted-by:' line is missing." + + # Extract the value, strip HTML comments and whitespace + ASSISTED_BY_VAL=$(grep -E "^[[:space:]]*(-\s+)?Assisted-by:" <<< "$PR_BODY" | sed -r -e 's/^[[:space:]]*(-\s+)?Assisted-by://' -e 's///' | tr -d '[:space:]') + if [ -z "$ASSISTED_BY_VAL" ]; then + echo "::error::You checked the AI tool checkbox in the PR template, but did not specify the tool that was used in 'Assisted-by:'." + exit 1 + fi + fi + + echo "PR Checklist verification passed." diff --git a/.github/workflows/pre-commit-run.yml b/.github/workflows/pre-commit-run.yml index c1addbb..56fc535 100644 --- a/.github/workflows/pre-commit-run.yml +++ b/.github/workflows/pre-commit-run.yml @@ -79,7 +79,7 @@ jobs: echo '::error:: ' echo '::error::Visit the docs below to configure pre-commit in your dev environment:' echo '::error:: ' - echo '::error:: https://beeware.org/contributing/how/process#code-style' + echo '::error:: https://beeware.org/contributing/guide/style/code-style-guide/' echo '::error:: ' echo '::error::*************************************************************************' exit 1 diff --git a/.github/workflows/pre-commit-update.yml b/.github/workflows/pre-commit-update.yml deleted file mode 100644 index 489ee4d..0000000 --- a/.github/workflows/pre-commit-update.yml +++ /dev/null @@ -1,148 +0,0 @@ -name: Update pre-commit - -####### -# Updates pre-commit's hooks, runs pre-commit, and commits all changes into a PR. -####### - -on: - schedule: - - cron: "0 20 * * SUN" # Sunday @ 2000 UTC - workflow_dispatch: - workflow_call: - inputs: - python-version: - description: "Python version to use; defaults to latest Python release." - default: "3.13" # TODO: restore to 3.x once docformatter is compatible with 3.14 - type: string - pre-commit-source: - description: "The arguments for `pip install` to install pre-commit; use ./path/to/package[dev] for the repo's pinned version." - default: ".[dev]" - type: string - create-changenote: - description: "Defaults 'true' to create a misc changenote in the './changes' directory." - default: true - type: boolean - changenote-format: - description: "Markup format for the changenote." - default: "rst" - type: string - secrets: - BRUTUS_PAT_TOKEN: - required: true - -permissions: - pull-requests: write - -env: - BRANCH_PREFIX: "autoupdates/pre-commit" - CHANGENOTE_DIR: "./changes" - FORCE_COLOR: "1" - -defaults: - run: - shell: bash - -jobs: - pre-commit-hooks: - name: Pre-commit hooks - runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - hook-repos: ${{ steps.hooks.outputs.repos }} - steps: - - name: Checkout Repo - uses: actions/checkout@v6 - - - name: Get Pre-commit Hooks - id: hooks - run: | - REPOS=$(yq .repos[].repo < .pre-commit-config.yaml | jq -R -s -c 'split("\n")[:-1]') - echo "repos=${REPOS}" >> ${GITHUB_OUTPUT} - - pre-commit-update: - name: Update Pre-commit hook - needs: pre-commit-hooks - runs-on: ubuntu-latest - timeout-minutes: 15 - strategy: - fail-fast: false - matrix: - hook-repo: ${{ fromJson(needs.pre-commit-hooks.outputs.hook-repos) }} - steps: - - name: Checkout - uses: actions/checkout@v6 - with: - fetch-depth: 1 - token: ${{ secrets.BRUTUS_PAT_TOKEN }} - - - name: Configure git - run: | - git config user.email "brutus@beeware.org" - git config user.name "Brutus (robot)" - - - name: Set up Python - uses: actions/setup-python@v6.2.0 - with: - python-version: ${{ inputs.python-version }} - allow-prereleases: true - cache: pip - cache-dependency-path: | - **/setup.cfg - **/pyproject.toml - .pre-commit-config.yaml - - - name: Install pre-commit - run: python -m pip install ${{ inputs.pre-commit-source || 'pre-commit' }} - - - name: Update pre-commit hooks - id: update - run: | - pre-commit autoupdate --repo ${{ matrix.hook-repo }} | tee update.log - echo "vers-bump-str=$(grep -ohE '([^ ]+ -> [^ ]+)' update.log | sed 's/->/to/')" >> ${GITHUB_OUTPUT} - rm -f update.log - pre-commit install-hooks - - - name: Run pre-commit - # pre-commit returns non-zero when files are changed and fails the job - continue-on-error: true - run: pre-commit run --all-files - - - name: PR Needed? - id: pr - run: | - if [[ $(git status --porcelain) ]]; then - echo "needed=true" >> ${GITHUB_OUTPUT} - else - echo "needed=false" >> ${GITHUB_OUTPUT} - fi - REPO="${{ matrix.hook-repo }}" - echo "hook-name=${REPO##*/}" >> ${GITHUB_OUTPUT} - - - name: Create Pull Request - id: created-pr - if: steps.pr.outputs.needed == 'true' - uses: peter-evans/create-pull-request@v8.1.1 - with: - token: ${{ secrets.BRUTUS_PAT_TOKEN }} - title: "Bump ${{ steps.pr.outputs.hook-name }} from ${{ steps.update.outputs.vers-bump-str }}" - branch: "${{ env.BRANCH_PREFIX }}/${{ steps.pr.outputs.hook-name }}" - commit-message: "Bump ${{ steps.pr.outputs.hook-name }} from ${{ steps.update.outputs.vers-bump-str }}" - committer: "Brutus (robot) " - author: "Brutus (robot) " - body: "Bumps `pre-commit` hook for `${{ steps.pr.outputs.hook-name }}` from ${{ steps.update.outputs.vers-bump-str }} and ran the update against the repo." - labels: "dependencies" - - - name: Add changenote - if: (inputs.create-changenote == true) && (steps.created-pr.outputs.pull-request-number != '') - run: | - BRANCH_NAME="${{ env.BRANCH_PREFIX }}/${{ steps.pr.outputs.hook-name }}" - - git fetch origin - git checkout "${BRANCH_NAME}" - - FILENAME="${{ env.CHANGENOTE_DIR }}/${{ steps.created-pr.outputs.pull-request-number }}.misc.${{ inputs.changenote-format }}" - printf 'The `pre-commit` hook for `${{ steps.pr.outputs.hook-name }}` was updated to its latest version.\n' > "${FILENAME}" - - git add "${FILENAME}" - git commit -m "Add changenote." - git push --set-upstream origin "${BRANCH_NAME}" diff --git a/.github/workflows/towncrier-run.yml b/.github/workflows/towncrier-run.yml index 3f6b3e2..356209c 100644 --- a/.github/workflows/towncrier-run.yml +++ b/.github/workflows/towncrier-run.yml @@ -24,6 +24,9 @@ on: default: "ubuntu-latest" type: string +permissions: + pull-requests: write + defaults: run: shell: bash @@ -71,6 +74,25 @@ jobs: id: tox run: tox -e towncrier-check + - name: Add PR comment if change note is missing + if: always() && github.event_name == 'pull_request' && steps.tox.outcome == 'failure' + env: + GITHUB_TOKEN: ${{ github.token }} + PR_NUM: ${{ github.event.pull_request.number }} + run: | + MESSAGE="Thank you for your pull request! Unfortunately, CI checks for this pull request are failing because you haven't included a change note in your contribution. Details on creating a change note can be found in the [BeeWare Contribution Guide](https://beeware.org/contributing/guide/how/change-note/). + + " + + COMMENTS=$(gh api repos/${{ github.repository }}/issues/${PR_NUM}/comments) + HAS_COMMENT=$(jq -r '.[] | select(.body | contains("")) | .body' <<< "$COMMENTS") + + if [ -z "$HAS_COMMENT" ]; then + gh api --method POST repos/${{ github.repository }}/issues/${PR_NUM}/comments -f body="$MESSAGE" + else + echo "Comment already exists." + fi + - name: Towncrier Check Resolution Instructions if: always() && steps.tox.outcome == 'failure' run: | @@ -83,7 +105,7 @@ jobs: echo '::error:: ' echo '::error::Visit the docs below to learn how to add a change note:' echo '::error:: ' - echo '::error:: https://beeware.org/contributing/how/process#change-notes' + echo '::error:: https://beeware.org/contributing/guide/how/change-note/' echo '::error:: ' echo '::error::*************************************************************************' exit 1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 227d0b9..8a2ddc9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,12 +9,12 @@ repos: - id: check-json - id: check-xml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.13 + rev: v0.15.14 hooks: - id: ruff-check args: [ --fix ] - id: ruff-format - repo: https://github.com/rvben/rumdl-pre-commit - rev: v0.1.93 + rev: v0.2.0 hooks: - id: rumdl diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9bd7e8a..2f62390 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,4 +34,4 @@ We require that all new features have full user documentation. We have a [docume ### Pull Requests -We have a [process for submitting a PR](https://beeware.org/contributing/guide/how/submit-pr/) that all contributions must follow. +We have a [process for submitting a PR](https://beeware.org/contributing/guide/how/submit-pr/) that all contributions must follow. This includes the use of a [pull request template](https://github.com/beeware/.github/blob/main/.github/pull_request_template.md) that *all* pull requests must include and complete as appropriate.