diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7da0f8a015a..8a855b1524c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ on: workflow_dispatch: { } permissions: - actions: read + actions: write # dispatch fmt-fix workflow on format failure contents: read checks: write # audit-check creates checks issues: write # audit-check creates issues @@ -197,8 +197,48 @@ jobs: - uses: ./.github/actions/setup-prebuild - run: cargo minimal-versions check --direct --workspace --ignore-private + rust-fmt: + name: "Rust (fmt)" + timeout-minutes: 10 + outputs: + fmt-failed: ${{ steps.fmt.outcome == 'failure' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: Install nightly for fmt + run: rustup toolchain install $NIGHTLY_TOOLCHAIN --component rustfmt + - name: Rust Lint - Format + id: fmt + continue-on-error: true + run: cargo +$NIGHTLY_TOOLCHAIN fmt --all --check + - name: Fail if fmt failed + if: steps.fmt.outcome == 'failure' + run: exit 1 + + dispatch-fmt-fix: + name: "Dispatch fmt-fix" + needs: rust-fmt + if: always() && needs.rust-fmt.outputs.fmt-failed == 'true' && github.event_name == 'pull_request' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + with: + script: | + await github.rest.actions.createWorkflowDispatch({ + ...context.repo, + workflow_id: 'fmt-fix.yml', + ref: 'develop', + inputs: { + 'pr-head-sha': context.payload.pull_request.head.sha, + 'pr-head-ref': context.payload.pull_request.head.ref, + }, + }); + rust-lint: name: "Rust (lint)" + needs: rust-fmt + if: always() timeout-minutes: 30 runs-on: >- ${{ github.repository == 'vortex-data/vortex' @@ -211,12 +251,6 @@ jobs: sccache: s3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: ./.github/actions/setup-prebuild - - name: Install nightly for fmt - run: rustup toolchain install $NIGHTLY_TOOLCHAIN --component rustfmt - - name: Rust Lint - Format - id: fmt - continue-on-error: true - run: cargo +$NIGHTLY_TOOLCHAIN fmt --all --check - name: Rustc check id: check continue-on-error: true @@ -239,7 +273,7 @@ jobs: with: script: | const failed = Object.entries({ - fmt: '${{ steps.fmt.outcome }}', + fmt: '${{ needs.rust-fmt.outputs.fmt-failed == 'true' && 'failure' || 'success' }}', check: '${{ steps.check.outcome }}', 'check-release': '${{ steps.check-release.outcome }}', 'clippy-all': '${{ steps.clippy-all.outcome }}', @@ -260,6 +294,7 @@ jobs: } core.setFailed(`Lint failed: ${failed.join(', ')}`); + cpp-lint: name: "C/C++ (lint)" runs-on: ubuntu-latest diff --git a/.github/workflows/fmt-fix.yml b/.github/workflows/fmt-fix.yml new file mode 100644 index 00000000000..af19d9f76fe --- /dev/null +++ b/.github/workflows/fmt-fix.yml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright the Vortex contributors + +name: Auto-fix formatting + +on: + workflow_dispatch: + inputs: + pr-head-sha: + description: "The PR head commit SHA to format" + required: true + type: string + pr-head-ref: + description: "The PR head branch name" + required: true + type: string + +env: + CARGO_TERM_COLOR: always + NIGHTLY_TOOLCHAIN: nightly-2026-02-05 + +jobs: + # Gate job: requires manual approval via the fmt-fix environment before + # the formatting commit is pushed. + approve: + name: "Approve formatting fix" + runs-on: ubuntu-latest + environment: fmt-fix + steps: + - run: echo "Formatting fix approved" + + apply-fmt: + name: "Apply formatting fix" + needs: approve + runs-on: ubuntu-latest + timeout-minutes: 15 + # Use the claude-automation environment to access the GitHub App secrets + # so the push triggers CI. + environment: + name: claude-automation + deployment: false + permissions: + contents: read + id-token: write + steps: + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + permission-contents: write + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ inputs.pr-head-sha }} + persist-credentials: false + + - name: Install nightly for fmt + run: rustup toolchain install $NIGHTLY_TOOLCHAIN --component rustfmt + + - name: Run cargo fmt + run: cargo +$NIGHTLY_TOOLCHAIN fmt --all + + - name: Commit and push + env: + EXPECTED_SHA: ${{ inputs.pr-head-sha }} + BRANCH: ${{ inputs.pr-head-ref }} + APP_TOKEN: ${{ steps.app-token.outputs.token }} + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add -A + git diff --cached --quiet && echo "No changes to commit" && exit 0 + git commit -m "chore: cargo fmt + + Signed-off-by: github-actions[bot] " + + # Use the App token so the push triggers CI. + git remote set-url origin \ + "https://x-access-token:${APP_TOKEN}@github.com/${{ github.repository }}.git" + + # --force-with-lease atomically checks that the remote branch HEAD + # is still EXPECTED_SHA before pushing. If someone else pushed a + # commit to the PR between trigger and approval, this fails safely. + git push origin \ + "HEAD:refs/heads/$BRANCH" \ + "--force-with-lease=refs/heads/$BRANCH:$EXPECTED_SHA" diff --git a/encodings/fastlanes/src/delta/array/delta_compress.rs b/encodings/fastlanes/src/delta/array/delta_compress.rs index e35778ad29e..d11a8bc0a8b 100644 --- a/encodings/fastlanes/src/delta/array/delta_compress.rs +++ b/encodings/fastlanes/src/delta/array/delta_compress.rs @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::mem; -use std::mem::MaybeUninit; +use std::mem::MaybeUninit; use fastlanes::Delta; use fastlanes::FastLanes;