diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..cc42102f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ + + +### What does this PR try to solve? + + +Closes # + +### Notes to reviewers + + + +LLM involvement: diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 144fe3a2..4bf63175 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,7 +1,10 @@ { + extends: ["helpers:pinGitHubActionDigests"], schedule: [ 'before 5am on the first day of the month', ], + minimumReleaseAge: "3 days", + internalChecksFilter: "strict", semanticCommits: 'enabled', commitMessageLowerCase: 'never', configMigration: true, @@ -64,11 +67,19 @@ matchDepNames: [ 'prek', ], - extractVersion: '^(?\\d+\\.\\d+\\.\\d+)', - schedule: [ - '* * * * *', + extractVersion: '^v(?\\d+\\.\\d+\\.\\d+)', + automerge: true, + }, + { + matchManagers: [ + 'github-actions', + ], + matchUpdateTypes: [ + 'minor', + 'patch', ], automerge: true, + groupName: 'compatible (actions)', }, // Goals: // - Rollup safe upgrades to reduce CI runner load diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 6e0a8a0c..bd52a484 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -1,13 +1,10 @@ -name: Security audit +name: Audit permissions: contents: read on: pull_request: - paths: - - '**/Cargo.toml' - - '**/Cargo.lock' push: branches: - master @@ -22,19 +19,38 @@ concurrency: cancel-in-progress: true jobs: - security_audit: + audit: + permissions: + contents: none + name: Audit + needs: [advisories, cargo_deny, actions] + runs-on: ubuntu-latest + if: "always()" + steps: + - name: Failed + run: exit 1 + if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')" + advisories: permissions: issues: write # to create issues (actions-rs/audit-check) checks: write # to create check (actions-rs/audit-check) runs-on: ubuntu-latest # Prevent sudden announcement of a new advisory from failing ci: continue-on-error: true + strategy: + matrix: + checks: + - advisories steps: - name: Checkout repository - uses: actions/checkout@v6 - - uses: actions-rs/audit-check@v1 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - token: ${{ secrets.GITHUB_TOKEN }} + persist-credentials: false + - name: Lint advisories + uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2.1.1 + with: + command: check ${{ matrix.checks }} + rust-version: stable cargo_deny: permissions: @@ -46,8 +62,26 @@ jobs: checks: - bans licenses sources steps: - - uses: actions/checkout@v6 - - uses: EmbarkStudios/cargo-deny-action@v2 + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Lint bans + uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2.1.1 with: command: check ${{ matrix.checks }} rust-version: stable + + actions: + runs-on: ubuntu-latest + permissions: + security-events: write + contents: read # only needed for private or internal repos + actions: read # only needed for private or internal repos + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Run zizmor + uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf9fdc78..b7bbb40d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,8 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 COLUMNS: 130 + CARGO_INCREMENTAL: 0 + RUST_TOOLCHAIN_STABLE: "1.98" # STABLE concurrency: group: "${{ github.workflow }}-${{ github.ref }}" @@ -44,14 +46,17 @@ jobs: CARGO_PROFILE_DEV_DEBUG: line-tables-only steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: ${{ matrix.rust }} - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - uses: taiki-e/install-action@cargo-hack + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + - name: Install cargo-hack + uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0 + with: + tool: cargo-hack - name: Build run: cargo test --workspace --no-run - name: Test @@ -64,13 +69,17 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: stable - - uses: Swatinem/rust-cache@v2 - - uses: taiki-e/install-action@cargo-hack + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update stable && rustup default stable + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + - name: Install cargo-hack + uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0 + with: + tool: cargo-hack - name: Default features run: cargo hack check --each-feature --locked --rust-version --ignore-private --workspace --all-targets --keep-going wasm: @@ -87,24 +96,24 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: stable - targets: ${{ matrix.target }} + persist-credentials: false + - name: Install Rust + run: rustup toolchain install stable --target ${{ matrix.target }} && rustup default stable - name: Default features run: cargo check -p typos -p typos-dict lockfile: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: stable - - uses: Swatinem/rust-cache@v2 + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update stable && rustup default stable + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: "Is lockfile updated?" run: cargo update --workspace --locked docs: @@ -112,28 +121,31 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: "1.98" # STABLE - - uses: Swatinem/rust-cache@v2 + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update $RUST_TOOLCHAIN_STABLE && rustup default $RUST_TOOLCHAIN_STABLE + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: Check documentation env: - RUSTDOCFLAGS: -D warnings + CARGO_BUILD_WARNINGS: deny run: cargo doc --workspace --all-features --no-deps --document-private-items --keep-going rustfmt: name: rustfmt runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: "1.98" # STABLE - components: rustfmt - - uses: Swatinem/rust-cache@v2 + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update $RUST_TOOLCHAIN_STABLE && rustup default $RUST_TOOLCHAIN_STABLE + - name: Install rustfmt + run: rustup component add rustfmt + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: Check formatting run: cargo fmt --check clippy: @@ -143,13 +155,15 @@ jobs: security-events: write # to upload sarif results steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: "1.98" # STABLE - components: clippy - - uses: Swatinem/rust-cache@v2 + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update $RUST_TOOLCHAIN_STABLE && rustup default $RUST_TOOLCHAIN_STABLE + - name: Install clippy + run: rustup component add clippy + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: Install SARIF tools run: cargo install clippy-sarif --locked - name: Install SARIF tools @@ -162,28 +176,35 @@ jobs: | sarif-fmt continue-on-error: true - name: Upload - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 with: sarif_file: clippy-results.sarif wait-for-processing: true - name: Report status - run: cargo clippy --workspace --all-features --all-targets --keep-going -- -D warnings --allow deprecated + env: + CARGO_BUILD_WARNINGS: deny + run: cargo clippy --workspace --all-features --all-targets --keep-going -- --allow deprecated --allow renamed_and_removed_lints coverage: name: Coverage runs-on: ubuntu-latest + permissions: + code-quality: write steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - toolchain: stable - - uses: Swatinem/rust-cache@v2 + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update stable && rustup default stable + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: Install cargo-tarpaulin run: cargo install cargo-tarpaulin - name: Gather coverage - run: cargo tarpaulin --output-dir coverage --out lcov - - name: Publish to Coveralls - uses: coverallsapp/github-action@master + run: cargo tarpaulin --out xml + - name: Upload coverage report + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + uses: actions/upload-code-coverage@d8e329117199404bba6fc81efe8093dc7c015e34 # v1.4.2 with: - github-token: ${{ secrets.GITHUB_TOKEN }} + file: cobertura.xml + language: Rust diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml index 9138a8e3..773fcd01 100644 --- a/.github/workflows/committed.yml +++ b/.github/workflows/committed.yml @@ -20,9 +20,11 @@ jobs: name: Lint Commits runs-on: ubuntu-latest steps: - - name: Checkout Actions Repository - uses: actions/checkout@v6 + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + filter: "tree:0" + persist-credentials: false - name: Lint Commits - uses: crate-ci/committed@master + uses: crate-ci/committed@faeed42f2e10c244533a01525f13c4d8b6ce383f # v1.1.11 diff --git a/.github/workflows/post-release.yml b/.github/workflows/post-release.yml index 876a5510..d76f790c 100644 --- a/.github/workflows/post-release.yml +++ b/.github/workflows/post-release.yml @@ -14,6 +14,10 @@ # https://eugene-babichenko.github.io/blog/2020/05/09/github-actions-cross-platform-auto-releases/ name: post-release + +permissions: + contents: read + on: push: tags: @@ -23,36 +27,37 @@ on: env: BIN_NAME: typos -# We need this to be able to create releases. -permissions: - contents: write - jobs: create-release: + permissions: + contents: write name: create-release runs-on: ubuntu-latest outputs: tag: ${{ env.TAG }} steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 1 + persist-credentials: false - name: Get the release version from the tag if: env.TAG == '' - run: echo "TAG=${{ github.ref_name }}" >> $GITHUB_ENV + run: echo "TAG=${GITHUB_REF_NAME}" >> $GITHUB_ENV - name: Show the tag run: | echo "tag is: $TAG" - name: Generate Release Notes run: | - ./.github/workflows/release-notes.py --tag ${{ env.TAG }} --output notes-${{ env.TAG }}.md - cat notes-${{ env.TAG }}.md + ./.github/workflows/release-notes.py --tag ${TAG} --output notes-${TAG}.md + cat notes-${TAG}.md - name: Create GitHub release env: GH_TOKEN: ${{ github.token }} - run: gh release create $TAG --verify-tag --draft --title $TAG --notes-file notes-${{ env.TAG }}.md + run: gh release create $TAG --verify-tag --draft --title $TAG --notes-file notes-${TAG}.md build-release: + permissions: + contents: write name: build-release needs: create-release strategy: @@ -83,26 +88,24 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 1 + persist-credentials: false - name: Install packages (Ubuntu) if: matrix.build == 'linux' || matrix.build == 'linux-aarch64' run: | sudo apt-get update sudo apt-get install -y --no-install-recommends xz-utils liblz4-tool musl-tools - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: ${{ matrix.rust }} - targets: ${{ matrix.target }} + run: rustup toolchain install ${{ matrix.rust }} --target ${{ matrix.target }} && rustup default ${{ matrix.rust }} - name: Build release binary run: cargo build --target ${{ matrix.target }} --verbose --release - name: Build archive shell: bash run: | outdir="./target/${{ matrix.target }}/release" - staging="${{ env.BIN_NAME }}-${{ needs.create-release.outputs.tag }}-${{ matrix.target }}" + staging="${{ env.BIN_NAME }}-${NEEDS_CREATE_RELEASE_OUTPUTS_TAG}-${{ matrix.target }}" mkdir -p "$staging"/doc cp {README.md,LICENSE-*} "$staging/" cp {CHANGELOG.md,docs/*} "$staging/doc/" @@ -118,27 +121,30 @@ jobs: tar czf "$staging.tar.gz" -C "$staging" . echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV fi + env: + NEEDS_CREATE_RELEASE_OUTPUTS_TAG: ${{ needs.create-release.outputs.tag }} - name: Upload release archive env: GH_TOKEN: ${{ github.token }} + NEEDS_CREATE_RELEASE_OUTPUTS_TAG: ${{ needs.create-release.outputs.tag }} shell: bash run: | - tag="${{ needs.create-release.outputs.tag }}" - gh release upload "$tag" ${{ env.ASSET }} + tag="${NEEDS_CREATE_RELEASE_OUTPUTS_TAG}" + gh release upload "$tag" ${ASSET} publish-release: + permissions: + contents: write name: Publish Release needs: [create-release, build-release] runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 1 + persist-credentials: false - name: Publish Release env: GH_TOKEN: ${{ github.token }} - run: gh release edit "${{ needs.create-release.outputs.tag }}" --draft=false - - name: Update major tag - uses: rickstaa/action-update-semver@v1 - with: - major_version_tag_only: true + NEEDS_CREATE_RELEASE_OUTPUTS_TAG: ${{ needs.create-release.outputs.tag }} + run: gh release edit "${NEEDS_CREATE_RELEASE_OUTPUTS_TAG}" --draft=false diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 70599be7..e145752a 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -22,7 +22,19 @@ jobs: contents: read runs-on: ubuntu-latest steps: +<<<<<<< HEAD - uses: actions/checkout@v6 - uses: j178/prek-action@v2 +||||||| e4f2b351 + - uses: actions/checkout@v6 + - uses: j178/prek-action@v1 +======= + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 +>>>>>>> _rust/main with: - prek-version: '0.2.27' + persist-credentials: false + - name: prek + uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0 + with: + prek-version: '0.5.0' diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index 3b4a2056..654ed08b 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -11,7 +11,12 @@ env: RUST_BACKTRACE: 1 CARGO_TERM_COLOR: always CLICOLOR: 1 +<<<<<<< HEAD COLUMNS: 130 +||||||| e4f2b351 +======= + CARGO_INCREMENTAL: 0 +>>>>>>> _rust/main concurrency: group: "${{ github.workflow }}-${{ github.ref }}" @@ -34,14 +39,28 @@ jobs: CARGO_PROFILE_DEV_DEBUG: line-tables-only steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: +<<<<<<< HEAD toolchain: ${{ matrix.rust }} components: rustfmt - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@cargo-hack +||||||| e4f2b351 + toolchain: ${{ matrix.rust }} + - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack +======= + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + - name: Install cargo-hack + uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0 + with: + tool: cargo-hack +>>>>>>> _rust/main - name: Build run: cargo test --workspace --no-run - name: Test @@ -56,14 +75,28 @@ jobs: CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: allow steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: +<<<<<<< HEAD toolchain: stable components: rustfmt - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@cargo-hack +||||||| e4f2b351 + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack +======= + persist-credentials: false + - name: Install Rust + run: rustup update --no-self-update stable && rustup default stable + - name: Initialize cache + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + - name: Install cargo-hack + uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0 + with: + tool: cargo-hack +>>>>>>> _rust/main - name: Update dependencies run: cargo update - name: Build diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 1d4fd850..76121eef 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -28,12 +28,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + persist-credentials: true # to push the branch and create PR - name: Configure git run: | - git config --global user.name '${{ github.actor }}' + git config --global user.name '${GITHUB_ACTOR}' git config --global user.email '<>' - name: Fetch template run: "git remote add template ${{ env.TEMPLATE_URL }} && git fetch template ${{ env.TEMPLATE_BRANCH }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 17be30c1..ec375d0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,3 +13,7 @@ repos: rev: v1.1.11 hooks: - id: committed + - repo: https://github.com/zizmorcore/zizmor-pre-commit + rev: v1.28.0 + hooks: + - id: zizmor diff --git a/AI_POLICY.md b/AI_POLICY.md new file mode 100644 index 00000000..b2ad65fd --- /dev/null +++ b/AI_POLICY.md @@ -0,0 +1,58 @@ +# AI policy + +Project maintainers are responsible for any code that is published as part of a release. +Contributors are responsible for their contributions, both in terms of communications and code. +This responsibility is for both understanding of and the quality of their contributions. + +## Personal use + +You are free to use an AI locally for your own purposes, +including to answer your questions, analyze, distill, refine, check, suggest, and review. + +## Communication + +**AI should not be used to generate comments when communicating with maintainers.** +We expect comments on our projects to be written by humans. +We may hide or delete any comments where we believe AI generation was involved. + +If you are opening an issue, +we expect you to have personally reproduced the problem and to describe it in your own words. + +If you are opening a pull request, +we expect you to be able to explain the proposed changes in your own words. +This includes the pull request body and responses to questions. +**Do not copy responses from an AI when replying to questions from maintainers.** +Do not run agents or bots on pull requests without first getting approval. + +We understand that AI is useful when communicating as a non-native English speaker. +If you are using AI to edit your comments for this purpose, +please take the time to ensure it reflects your own voice and ideas. +If using AI for translation, we recommend writing in your native language and including the AI translation in a [`
` block]. + +If you wish to include context from an interaction with AI in your comments, +it must be in a [`
` block] and disclosed as such. +The block must include human commentary explaining the relevance and implications of the context. +The content of your comment must stand on its own even without the quoted content. +Do not share long snippets. + +## Code + +Using AI as tools for coding requires receiving permission on the relevant issue before a PR is posted. + +This project requires a human in the loop who understands the work produced by AI. +**We do not allow autonomous agents to be used for contributing to this project**. +We will close any pull requests that we believe were created **without meaningful involvement** from the contributor. +Contributions should not "read" as being written by an AI. + +Some areas require specific expertise or care when touching. +AI generated code, even with human review, is prohibited for: +- none + +We view AI as providing a way to improve quality and will hold AI-assisted contributions to a higher standard. +We will be more free in asking for changes. + +The involvement of AI assistance must be disclosed in PRs. + +For documentation, including comments in code, see [Communication](#communication). + +[`
` block]: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections) diff --git a/Cargo.toml b/Cargo.toml index cc87dc45..1ca807e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,17 +11,20 @@ license = "MIT OR Apache-2.0" edition = "2024" rust-version = "1.95" # MSRV include = [ - "build.rs", - "src/**/*", - "Cargo.toml", - "Cargo.lock", - "LICENSE*", - "README.md", - "examples/**/*" + "/build.rs", + "/src/**/*", + "/Cargo.toml", + "/Cargo.lock", + "/LICENSE*", + "/README.md", + "/examples/**/*" ] [workspace.lints.rust] rust_2018_idioms = { level = "warn", priority = -1 } + +non_ascii_idents = "warn" +trivial_numeric_casts = "warn" unnameable_types = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" @@ -30,12 +33,18 @@ unused_macro_rules = "warn" unused_qualifications = "warn" [workspace.lints.clippy] +#allow_attributes_without_reason = "warn" bool_assert_comparison = "allow" branches_sharing_code = "allow" byte_char_slices = "allow" # sometimes explicit arrays are better +#cast_possible_truncation = "warn" +#cast_possible_wrap = "warn" +#cast_sign_loss = "warn" checked_conversions = "warn" collapsible_else_if = "allow" collapsible_if = "allow" +collapsible_match = "allow" +collection_is_never_read = "warn" create_dir = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" @@ -48,9 +57,10 @@ explicit_into_iter_loop = "warn" fallible_impl_from = "warn" filter_map_next = "warn" flat_map_option = "warn" +float_cmp = "warn" float_cmp_const = "warn" fn_params_excessive_bools = "warn" -from_iter_instead_of_collect = "warn" +fn_to_numeric_cast_any = "warn" if_same_then_else = "allow" implicit_clone = "warn" imprecise_flops = "warn" @@ -66,10 +76,12 @@ linkedlist = "warn" lossy_float_literal = "warn" macro_use_imports = "warn" mem_forget = "warn" +mismatching_type_param_order = "warn" mutex_integer = "warn" needless_continue = "allow" needless_for_each = "warn" negative_feature_names = "warn" +partial_pub_fields = "warn" path_buf_push_overwrite = "warn" ptr_as_ptr = "warn" rc_mutex = "warn" @@ -80,13 +92,19 @@ result_large_err = "allow" same_functions_in_if_condition = "warn" self_named_module_files = "warn" semicolon_if_nothing_returned = "warn" +should_panic_without_expect = "warn" str_to_string = "warn" string_add = "warn" string_add_assign = "warn" string_lit_as_bytes = "warn" todo = "warn" trait_duplication_in_bounds = "warn" +#undocumented_unsafe_blocks = "warn" uninlined_format_args = "warn" +unnecessary_safety_comment = "warn" +unnecessary_safety_doc = "warn" +unseparated_literal_suffix = "warn" +use_self = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 8f71f43f..6aa81fe0 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright Individual contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/crates/typos-cli/Cargo.toml b/crates/typos-cli/Cargo.toml index 652c27bd..f070ae54 100644 --- a/crates/typos-cli/Cargo.toml +++ b/crates/typos-cli/Cargo.toml @@ -22,7 +22,7 @@ pre-release-replacements = [ {file="../../CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1}, {file="../../CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, {file="../../CHANGELOG.md", search="", replace="\n## [Unreleased] - ReleaseDate\n", exactly=1}, - {file="../../CHANGELOG.md", search="", replace="\n[Unreleased]: https://github.com/crate-ci/typos/compare/{{tag_name}}...HEAD", exactly=1}, + {file="../../CHANGELOG.md", search="", replace="\n[Unreleased]: {{repository}}/compare/{{tag_name}}...HEAD", exactly=1}, {file="../../action/entrypoint.sh", search="VERSION=.*", replace="VERSION={{version}}", min=1}, {file="../../docs/pre-commit.md", search="rev: .*", replace="rev: {{tag_name}}", exactly=1}, {file="../../docs/github-action.md", search="uses: crate-ci/typos@.*", replace="uses: crate-ci/typos@{{tag_name}}", min=1}, diff --git a/crates/typos-cli/src/bin/typos-cli/args.rs b/crates/typos-cli/src/bin/typos-cli/args.rs index 6ead0eb2..ca3eea0d 100644 --- a/crates/typos-cli/src/bin/typos-cli/args.rs +++ b/crates/typos-cli/src/bin/typos-cli/args.rs @@ -16,11 +16,11 @@ pub(crate) enum Format { impl Format { pub(crate) fn reporter(self) -> Box { match self { - Format::Silent => Box::new(crate::report::PrintSilent), - Format::Brief => Box::new(crate::report::PrintBrief), - Format::Long => Box::new(crate::report::PrintLong), - Format::Json => Box::new(crate::report::PrintJson), - Format::Sarif => Box::new(crate::report::PrintSarif::default()), + Self::Silent => Box::new(crate::report::PrintSilent), + Self::Brief => Box::new(crate::report::PrintBrief), + Self::Long => Box::new(crate::report::PrintLong), + Self::Json => Box::new(crate::report::PrintJson), + Self::Sarif => Box::new(crate::report::PrintSarif::default()), } } } diff --git a/crates/typos-cli/src/config.rs b/crates/typos-cli/src/config.rs index 2598cf2e..06836a55 100644 --- a/crates/typos-cli/src/config.rs +++ b/crates/typos-cli/src/config.rs @@ -138,7 +138,7 @@ impl Config { } } - pub fn update(&mut self, source: &Config) { + pub fn update(&mut self, source: &Self) { self.files.update(&source.files); self.default.update(&source.default); self.type_.update(&source.type_); @@ -194,7 +194,7 @@ impl Walk { } } - pub fn update(&mut self, source: &Walk) { + pub fn update(&mut self, source: &Self) { self.extend_exclude .extend(source.extend_exclude.iter().cloned()); if let Some(source) = source.ignore_hidden { @@ -337,7 +337,7 @@ pub struct GlobEngineConfig { } impl GlobEngineConfig { - pub fn update(&mut self, source: &GlobEngineConfig) { + pub fn update(&mut self, source: &Self) { self.extend_glob.extend(source.extend_glob.iter().cloned()); self.engine.update(&source.engine); } @@ -370,7 +370,7 @@ pub struct EngineConfig { impl EngineConfig { pub fn from_defaults() -> Self { let empty = Self::default(); - EngineConfig { + Self { binary: Some(empty.binary()), check_filename: Some(empty.check_filename()), check_file: Some(empty.check_file()), @@ -381,7 +381,7 @@ impl EngineConfig { } } - pub fn update(&mut self, source: &EngineConfig) { + pub fn update(&mut self, source: &Self) { if let Some(source) = source.binary { self.binary = Some(source); } @@ -439,7 +439,7 @@ impl TokenizerConfig { } } - pub fn update(&mut self, source: &TokenizerConfig) { + pub fn update(&mut self, source: &Self) { if let Some(source) = source.unicode { self.unicode = Some(source); } @@ -501,7 +501,7 @@ impl DictConfig { } } - pub fn update(&mut self, source: &DictConfig) { + pub fn update(&mut self, source: &Self) { if let Some(source) = source.locale { self.locale = Some(source); } @@ -578,11 +578,11 @@ pub enum Locale { impl Locale { pub const fn category(self) -> Option { match self { - Locale::En => None, - Locale::EnUs => Some(varcon_core::Category::American), - Locale::EnGb => Some(varcon_core::Category::BritishIse), - Locale::EnCa => Some(varcon_core::Category::Canadian), - Locale::EnAu => Some(varcon_core::Category::Australian), + Self::En => None, + Self::EnUs => Some(varcon_core::Category::American), + Self::EnGb => Some(varcon_core::Category::BritishIse), + Self::EnCa => Some(varcon_core::Category::Canadian), + Self::EnAu => Some(varcon_core::Category::Australian), } } @@ -596,11 +596,11 @@ impl std::str::FromStr for Locale { fn from_str(s: &str) -> Result { match s { - "en" => Ok(Locale::En), - "en-us" => Ok(Locale::EnUs), - "en-gb" => Ok(Locale::EnGb), - "en-ca" => Ok(Locale::EnCa), - "en-au" => Ok(Locale::EnAu), + "en" => Ok(Self::En), + "en-us" => Ok(Self::EnUs), + "en-gb" => Ok(Self::EnGb), + "en-ca" => Ok(Self::EnCa), + "en-au" => Ok(Self::EnAu), _ => Err("valid values: en, en-us, en-gb, en-ca, en-au".to_owned()), } } @@ -609,11 +609,11 @@ impl std::str::FromStr for Locale { impl std::fmt::Display for Locale { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { - Locale::En => write!(f, "en"), - Locale::EnUs => write!(f, "en-us"), - Locale::EnGb => write!(f, "en-gb"), - Locale::EnCa => write!(f, "en-ca"), - Locale::EnAu => write!(f, "en-au"), + Self::En => write!(f, "en"), + Self::EnUs => write!(f, "en-us"), + Self::EnGb => write!(f, "en-gb"), + Self::EnCa => write!(f, "en-ca"), + Self::EnAu => write!(f, "en-au"), } } } diff --git a/crates/typos-cli/src/dict.rs b/crates/typos-cli/src/dict.rs index bb540ca2..c879c635 100644 --- a/crates/typos-cli/src/dict.rs +++ b/crates/typos-cli/src/dict.rs @@ -177,11 +177,11 @@ impl BuiltIn { impl typos::Dictionary for BuiltIn { fn correct_ident<'s>(&'s self, ident: typos::tokens::Identifier<'_>) -> Option> { - BuiltIn::correct_ident(self, ident) + Self::correct_ident(self, ident) } fn correct_word<'s>(&'s self, word: typos::tokens::Word<'_>) -> Option> { - BuiltIn::correct_word(self, word) + Self::correct_word(self, word) } } diff --git a/crates/typos-cli/src/file.rs b/crates/typos-cli/src/file.rs index 421ddc90..4fa831f7 100644 --- a/crates/typos-cli/src/file.rs +++ b/crates/typos-cli/src/file.rs @@ -876,7 +876,7 @@ fn is_fixable(typo: &typos::Typo<'_>) -> bool { } fn fix_buffer(mut buffer: Vec, typos: impl Iterator>) -> Vec { - let mut offset = 0isize; + let mut offset = 0_isize; for typo in typos { let fix = extract_fix(&typo).expect("Caller only provides fixable typos"); let start = ((typo.byte_offset as isize) + offset) as usize; diff --git a/crates/typos-vars/tests/codegen.rs b/crates/typos-vars/tests/codegen.rs index e90579ce..a54925f0 100644 --- a/crates/typos-vars/tests/codegen.rs +++ b/crates/typos-vars/tests/codegen.rs @@ -258,16 +258,11 @@ fn collect_correct(entry: &varcon_core::Entry, category: varcon::Category) -> Ha } fn ignore_variant(variant: &varcon_core::Variant) -> bool { - if variant.word == "anesthetisation" + variant.word == "anesthetisation" && variant.types.len() == 1 && variant.types[0].category == varcon::Category::Australian && (variant.types[0].tag == Some(varcon::Tag::Variant) || variant.types[0].tag == Some(varcon::Tag::Seldom)) - { - return true; - } - - false } // dict needs diff --git a/crates/typos/src/tokens.rs b/crates/typos/src/tokens.rs index 111dc06d..eed9675f 100644 --- a/crates/typos/src/tokens.rs +++ b/crates/typos/src/tokens.rs @@ -976,28 +976,28 @@ enum WordMode { impl WordMode { fn classify(c: char) -> Self { if c.is_lowercase() { - WordMode::Lowercase + Self::Lowercase } else if c.is_uppercase() { - WordMode::Uppercase + Self::Uppercase } else if c.is_ascii_digit() { - WordMode::Number + Self::Number } else { // This assumes all characters are either lower or upper case. - WordMode::Boundary + Self::Boundary } } - fn case(self, last: WordMode) -> Case { + fn case(self, last: Self) -> Case { match (self, last) { - (WordMode::Uppercase, WordMode::Uppercase) => Case::Upper, - (WordMode::Uppercase, WordMode::Lowercase) => Case::Title, - (WordMode::Lowercase, WordMode::Lowercase) => Case::Lower, - (WordMode::Number, WordMode::Number) => Case::None, - (WordMode::Number, _) - | (_, WordMode::Number) - | (WordMode::Boundary, _) - | (_, WordMode::Boundary) - | (WordMode::Lowercase, WordMode::Uppercase) => { + (Self::Uppercase, Self::Uppercase) => Case::Upper, + (Self::Uppercase, Self::Lowercase) => Case::Title, + (Self::Lowercase, Self::Lowercase) => Case::Lower, + (Self::Number, Self::Number) => Case::None, + (Self::Number, _) + | (_, Self::Number) + | (Self::Boundary, _) + | (_, Self::Boundary) + | (Self::Lowercase, Self::Uppercase) => { unreachable!("Invalid case combination: ({:?}, {:?})", self, last) } } @@ -2258,7 +2258,7 @@ mod test { let cases = [ ( "lowercase", - &[("lowercase", Case::Lower, 0usize)] as &[(&str, Case, usize)], + &[("lowercase", Case::Lower, 0_usize)] as &[(&str, Case, usize)], ), ("Class", &[("Class", Case::Title, 0)]), ( diff --git a/crates/varcon-core/src/parser.rs b/crates/varcon-core/src/parser.rs index 443873ce..c98464f5 100644 --- a/crates/varcon-core/src/parser.rs +++ b/crates/varcon-core/src/parser.rs @@ -1734,13 +1734,13 @@ impl Type { Self::parse_.parse(input).map_err(|_err| ParseError) } - fn parse_(input: &mut &str) -> ModalResult { + fn parse_(input: &mut &str) -> ModalResult { trace("type", move |input: &mut &str| { let category = Category::parse_(input)?; let tag = opt(Tag::parse_).parse_next(input)?; let num = opt(winnow::ascii::digit1).parse_next(input)?; let num = num.map(|s| s.parse().expect("parser ensured it's a number")); - let t = Type { category, tag, num }; + let t = Self { category, tag, num }; Ok(t) }) .parse_next(input) @@ -1855,12 +1855,12 @@ impl Category { let symbols = one_of(['A', 'B', 'Z', 'C', 'D', '_']); symbols .map(|c| match c { - 'A' => Category::American, - 'B' => Category::BritishIse, - 'Z' => Category::BritishIze, - 'C' => Category::Canadian, - 'D' => Category::Australian, - '_' => Category::Other, + 'A' => Self::American, + 'B' => Self::BritishIse, + 'Z' => Self::BritishIze, + 'C' => Self::Canadian, + 'D' => Self::Australian, + '_' => Self::Other, _ => unreachable!("parser won't select this option"), }) .parse_next(input) @@ -1914,11 +1914,11 @@ impl Tag { let symbols = one_of(['.', 'v', 'V', '-', 'x']); symbols .map(|c| match c { - '.' => Tag::Eq, - 'v' => Tag::Variant, - 'V' => Tag::Seldom, - '-' => Tag::Possible, - 'x' => Tag::Improper, + '.' => Self::Eq, + 'v' => Self::Variant, + 'V' => Self::Seldom, + '-' => Self::Possible, + 'x' => Self::Improper, _ => unreachable!("parser won't select this option"), }) .parse_next(input) @@ -1970,13 +1970,13 @@ impl Pos { fn parse_(input: &mut &str) -> ModalResult { trace("pos", move |input: &mut &str| { alt(( - "N".value(Pos::Noun), - "V".value(Pos::Verb), - "Adj".value(Pos::Adjective), - "Adv".value(Pos::Adverb), - "A".value(Pos::AdjectiveOrAdverb), - "Inj".value(Pos::Interjection), - "Prep".value(Pos::Preposition), + "N".value(Self::Noun), + "V".value(Self::Verb), + "Adj".value(Self::Adjective), + "Adv".value(Self::Adverb), + "A".value(Self::AdjectiveOrAdverb), + "Inj".value(Self::Interjection), + "Prep".value(Self::Preposition), )) .parse_next(input) }) diff --git a/deny.toml b/deny.toml index 27bf59a8..c617b413 100644 --- a/deny.toml +++ b/deny.toml @@ -97,6 +97,7 @@ allow = [ "OpenSSL", "Zlib", "NCSA", + "CDLA-Permissive-2.0", ] # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the