Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
time: "02:00"
open-pull-requests-limit: 10

# Maintain dependencies for GitHub Actions
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
groups:
all-actions-version-updates:
applies-to: version-updates
patterns:
- "*"
all-actions-security-updates:
applies-to: security-updates
patterns:
- "*"

# Update Rust dependencies
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
time: "02:00"
open-pull-requests-limit: 10
groups:
all-cargo-version-updates:
applies-to: version-updates
patterns:
- "*"
all-cargo-security-updates:
applies-to: security-updates
patterns:
- "*"
82 changes: 56 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,60 +18,90 @@ jobs:
name: Test
runs-on: ubuntu-latest
steps:
- uses: taiki-e/install-action@v2
with: { tool: 'just,cargo-llvm-cov' }
- uses: actions/checkout@v4
with: { submodules: recursive }
- if: github.event_name != 'release' && github.event_name != 'workflow_dispatch'
uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with: { tool: just }
- if: github.event_name == 'release'
name: Ensure this crate has not yet been published (on release)
run: just check-if-published
- if: github.event_name != 'release' && github.event_name != 'workflow_dispatch'
uses: Swatinem/rust-cache@v2
- run: RUST_BACKTRACE=1 just -v ci-test
- run: just ci-test
- name: Check semver
uses: obi1kenobi/cargo-semver-checks-action@v2
- if: github.event_name != 'release' && github.event_name != 'workflow_dispatch'
name: Generate code coverage
run: just ci-coverage
- if: github.event_name != 'release' && github.event_name != 'workflow_dispatch'
name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/llvm-cov/codecov.info
fail_ci_if_error: false
- name: Test packaging for publish
run: |
rustup install nightly --profile minimal
just test-publish

msrv:
name: Test MSRV
test-nightly:
name: Nightly-specific tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { submodules: recursive }
- if: github.event_name != 'release' && github.event_name != 'workflow_dispatch'
uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with: { tool: just }
- run: rustup install nightly --profile minimal
- run: just test-publish

test-msrv:
name: Test MSRV
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { submodules: recursive }
- if: github.event_name != 'release' && github.event_name != 'workflow_dispatch'
uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with: { tool: just }
- name: Read MSRV
id: msrv
run: echo "value=$(sed -ne 's/rust-version *= *\"\(.*\)\"/\1/p' Cargo.toml)" >> $GITHUB_OUTPUT
run: echo "value=$(just get-msrv)" >> $GITHUB_OUTPUT
- name: Install MSRV Rust ${{ steps.msrv.outputs.value }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ steps.msrv.outputs.value }}
components: rustfmt
- run: just -v ci-test-msrv
- run: just ci_mode=0 ci-test-msrv # Ignore warnings in MSRV

publish:
if: startsWith(github.ref, 'refs/tags/')
coverage:
name: Code Coverage
if: github.event_name != 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { submodules: recursive }
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with: { tool: 'just,cargo-llvm-cov' }
- name: Generate code coverage
run: just ci-coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/llvm-cov/codecov.info
fail_ci_if_error: true

# This job checks if any of the previous jobs failed or were canceled.
# This approach also allows some jobs to be skipped if they are not needed.
ci-passed:
if: always()
needs: [ test, test-nightly, test-msrv, coverage ]
runs-on: ubuntu-latest
steps:
- if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1

release:
# Some dependencies of the `ci-passed` job might be skipped, but we still want to run if the `ci-passed` job succeeded.
if: always() && startsWith(github.ref, 'refs/tags/') && needs.ci-passed.result == 'success'
name: Publish to crates.io
needs: [ test, msrv ]
needs: [ ci-passed ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { submodules: recursive }
- name: Publish to crates.io
run: cargo publish
env:
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
*.pdb
.idea/
.vscode/
Cargo.lock
codecov*
debug/
target/
temp/
tmp/
venv/

# This is a library, no lock
Cargo.lock
113 changes: 70 additions & 43 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
#!/usr/bin/env just --justfile

main_crate := 'fastpfor'

# if running in CI, treat warnings as errors by setting RUSTFLAGS and RUSTDOCFLAGS to '-D warnings' unless they are already set
# Use `CI=true just ci-test` to run the same tests as in GitHub CI.
# Use `just env-info` to see the current values of RUSTFLAGS and RUSTDOCFLAGS
ci_mode := if env('CI', '') != '' { '1' } else { '' }
export RUSTFLAGS := env('RUSTFLAGS', if ci_mode == '1' {'-D warnings'} else {''})
export RUSTDOCFLAGS := env('RUSTDOCFLAGS', if ci_mode == '1' {'-D warnings'} else {''})
export RUST_BACKTRACE := env('RUST_BACKTRACE', if ci_mode == '1' {'1'} else {''})

@_default:
just --list

# Run tests, and accept their results. Requires insta to be installed.
bless: (cargo-install "cargo-insta")
TRYBUILD=overwrite cargo insta test --accept --all-features
# Run integration tests and save its output as the new expected output
bless *args: (cargo-install 'cargo-insta')
TRYBUILD=overwrite cargo insta test --accept --unreferenced=delete --all-features

# Default build
build *ARGS:
cargo build --all-targets --workspace --all-features {{ARGS}}
# Build the project
build:
cargo build --workspace --all-targets --all-features

# Quick compile without building a binary
check:
cargo check --workspace --all-targets --all-features

# Verify that the current version of the crate is not the same as the one published on crates.io
check-if-published: (assert "jq")
check-if-published: (assert 'jq')
#!/usr/bin/env bash
set -euo pipefail
LOCAL_VERSION="$(grep '^version =' Cargo.toml | sed -E 's/version = "([^"]*)".*/\1/')"
echo "Detected crate version: $LOCAL_VERSION"
CRATE_NAME="$(grep '^name =' Cargo.toml | head -1 | sed -E 's/name = "(.*)"/\1/')"
echo "Detected crate name: $CRATE_NAME"
LOCAL_VERSION="$({{just_executable()}} get-crate-field version)"
echo "Detected crate version: '$LOCAL_VERSION'"
CRATE_NAME="$({{just_executable()}} get-crate-field name)"
echo "Detected crate name: '$CRATE_NAME'"
PUBLISHED_VERSION="$(cargo search ${CRATE_NAME} | grep "^${CRATE_NAME} =" | sed -E 's/.* = "(.*)".*/\1/')"
echo "Published crate version: $PUBLISHED_VERSION"
echo "Published crate version: '$PUBLISHED_VERSION'"
if [ "$LOCAL_VERSION" = "$PUBLISHED_VERSION" ]; then
echo "ERROR: The current crate version has already been published."
exit 1
Expand All @@ -39,64 +49,81 @@ ci-coverage: && \
mkdir -p target/llvm-cov

# Run all tests as expected by CI
ci-test: rust-info test-fmt
RUSTFLAGS='-D warnings' {{just_executable()}} build
{{just_executable()}} clippy -- -D warnings
RUSTFLAGS='-D warnings' {{just_executable()}} test
RUSTDOCFLAGS='-D warnings' {{just_executable()}} test-doc
ci-test: env-info test-fmt build clippy test test-doc
#!/usr/bin/env bash
set -euo pipefail
if [ -n "$(git status --untracked-files --porcelain)" ]; then
>&2 echo 'ERROR: git repo is no longer clean. Make sure compilation and tests artifacts are in the .gitignore, and no repo files are modified.'
>&2 echo '######### git status ##########'
git status
exit 1
fi

# Run minimal subset of tests to ensure compatibility with MSRV
ci-test-msrv: rust-info test
ci-test-msrv: env-info test

# Clean all build artifacts
clean:
cargo clean
rm -f Cargo.lock

# Run cargo clippy to lint the code
clippy *ARGS:
cargo clippy --workspace --all-targets --all-features {{ARGS}}
clippy *args:
cargo clippy --workspace --all-targets --all-features {{args}}

# Generate code coverage report
coverage *ARGS="--no-clean --open":
cargo llvm-cov test --workspace --all-targets --all-features --include-build-script {{ARGS}}
# Generate code coverage report. Will install `cargo llvm-cov` if missing.
coverage *args='--no-clean --open': (cargo-install 'cargo-llvm-cov')
cargo llvm-cov --workspace --all-targets --all-features --include-build-script {{args}}

# Build and open code documentation
docs:
cargo doc --no-deps --all-features --open

# Print environment info
env-info:
@echo "Running {{if ci_mode == '1' {'in CI mode'} else {'in dev mode'} }} on {{os()}} / {{arch()}}"
{{just_executable()}} --version
rustc --version
cargo --version
rustup --version
@echo "RUSTFLAGS='$RUSTFLAGS'"
@echo "RUSTDOCFLAGS='$RUSTDOCFLAGS'"

# Reformat all code `cargo fmt`. If nightly is available, use it for better results
fmt:
#!/usr/bin/env bash
set -euo pipefail
if command -v cargo +nightly &> /dev/null; then
if rustup component list --toolchain nightly | grep rustfmt &> /dev/null; then
echo 'Reformatting Rust code using nightly Rust fmt to sort imports'
cargo +nightly fmt --all -- --config imports_granularity=Module,group_imports=StdExternalCrate
else
echo 'Reformatting Rust with the stable cargo fmt. Install nightly with `rustup install nightly` for better results'
cargo fmt --all
fi

# Get any package's field from the metadata
get-crate-field field package=main_crate:
cargo metadata --format-version 1 | jq -r '.packages | map(select(.name == "{{package}}")) | first | .{{field}}'

# Get the minimum supported Rust version (MSRV) for the crate
get-msrv: (get-crate-field 'rust_version')

# Find the minimum supported Rust version (MSRV) using cargo-msrv extension, and update Cargo.toml
msrv:
msrv: (cargo-install 'cargo-msrv')
cargo msrv find --write-msrv --component rustfmt --all-features --ignore-lockfile -- {{just_executable()}} ci-test-msrv

rust-info:
rustc --version
cargo --version

# Check semver compatibility with prior published version. Install it with `cargo install cargo-semver-checks`
semver *ARGS:
cargo semver-checks {{ARGS}}
semver *args: (cargo-install 'cargo-semver-checks')
cargo semver-checks {{args}}

# Run all tests
test *ARGS:
cargo test --all-targets --workspace --all-features {{ARGS}}
test:
cargo test --workspace --all-targets --all-features

# Test documentation
test-doc:
cargo test --doc --all-features
cargo doc --no-deps --all-features
cargo doc --all-features --no-deps

# Test code formatting
test-fmt:
Expand All @@ -107,7 +134,7 @@ test-publish:
cargo +nightly -Z package-workspace publish --dry-run

# Find unused dependencies. Install it with `cargo install cargo-udeps`
udeps:
udeps: (cargo-install 'cargo-udeps')
cargo +nightly udeps --all-targets --workspace --all-features

# Update all dependencies, including breaking changes. Requires nightly toolchain (install with `rustup install nightly`)
Expand All @@ -117,23 +144,23 @@ update:

# Ensure that a certain command is available
[private]
assert $COMMAND:
@if ! type "{{COMMAND}}" > /dev/null; then \
echo "Command '{{COMMAND}}' could not be found. Please make sure it has been installed on your computer." ;\
assert command:
@if ! type {{command}} > /dev/null; then \
echo "Command '{{command}}' could not be found. Please make sure it has been installed on your computer." ;\
exit 1 ;\
fi

# Check if a certain Cargo command is installed, and install it if needed
[private]
cargo-install $COMMAND $INSTALL_CMD="" *ARGS="":
cargo-install $COMMAND $INSTALL_CMD='' *args='':
#!/usr/bin/env bash
set -euo pipefail
if ! command -v $COMMAND > /dev/null; then
if ! command -v cargo-binstall > /dev/null; then
echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} {{ARGS}}"
cargo install ${INSTALL_CMD:-$COMMAND} {{ARGS}}
echo "$COMMAND could not be found. Installing it with cargo install ${INSTALL_CMD:-$COMMAND} --locked {{args}}"
cargo install ${INSTALL_CMD:-$COMMAND} --locked {{args}}
else
echo "$COMMAND could not be found. Installing it with cargo binstall ${INSTALL_CMD:-$COMMAND} {{ARGS}}"
cargo binstall ${INSTALL_CMD:-$COMMAND} {{ARGS}}
echo "$COMMAND could not be found. Installing it with cargo binstall ${INSTALL_CMD:-$COMMAND} --locked {{args}}"
cargo binstall ${INSTALL_CMD:-$COMMAND} --locked {{args}}
fi
fi
3 changes: 1 addition & 2 deletions tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use fastpfor::rust::{
DEFAULT_PAGE_SIZE,
};
use rand::rngs::StdRng;
use rand::Rng as _;
use rand::SeedableRng as _;
use rand::{Rng as _, SeedableRng as _};

pub enum TestCodec {
VariableByte(VariableByte, String),
Expand Down
3 changes: 2 additions & 1 deletion tests/cpp_compat_tests.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![cfg(all(feature = "rust", feature = "cpp"))]

use std::io::Cursor;

use fastpfor::cpp::Codec32 as _;
use fastpfor::rust::Integer as _;
use fastpfor::{cpp, rust};
use std::io::Cursor;

mod common;
use common::{get_test_cases, test_input_sizes};
Expand Down