Skip to content

feat: allow globs to be passed into yek #439

feat: allow globs to be passed into yek

feat: allow globs to be passed into yek #439

Workflow file for this run

name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: short
OPENSSL_STATIC: true
PKG_CONFIG_ALLOW_CROSS: true
permissions:
contents: write
jobs:
determine-changes:
name: Determine Changes
runs-on: ubuntu-latest
outputs:
only_docs: ${{ steps.check.outputs.only_docs }}
only_tests: ${{ steps.check.outputs.only_tests }}
only_src: ${{ steps.check.outputs.only_src }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: check
run: |
changed_files="$(git diff --name-only HEAD^ HEAD || true)"
doc_pattern='^(docs/|README\.md|\.txt$|\.md$)'
test_pattern='^(tests/|test/)'
src_pattern='^(src/|Cargo\.toml|Cargo\.lock)'
only_docs=true
only_tests=true
only_src=true
if [ -z "$changed_files" ]; then
only_docs=false
only_tests=false
only_src=false
else
while IFS= read -r file; do
[[ "$file" =~ $doc_pattern ]] || only_docs=false
[[ "$file" =~ $test_pattern ]] || only_tests=false
[[ "$file" =~ $src_pattern ]] || only_src=false
done < <(echo "$changed_files")
fi
echo "only_docs=$only_docs" >> $GITHUB_OUTPUT
echo "only_tests=$only_tests" >> $GITHUB_OUTPUT
echo "only_src=$only_src" >> $GITHUB_OUTPUT
lint:
name: Lint
needs: determine-changes
runs-on: ubuntu-latest
if: >
needs.determine-changes.outputs.only_docs != 'true' &&
needs.determine-changes.outputs.only_tests != 'true' &&
needs.determine-changes.outputs.only_src != 'true'
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Clippy
run: cargo clippy -- -D warnings
- name: Format check
run: cargo fmt --check
test:
name: Test
needs: determine-changes
runs-on: ubuntu-latest
if: needs.determine-changes.outputs.only_docs != 'true'
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Install OpenSSL (Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libssl-dev
- name: Install OpenSSL (macOS)
if: runner.os == 'macOS'
run: |
brew install openssl@3
echo "OPENSSL_DIR=$(brew --prefix openssl@3)" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=$(brew --prefix openssl@3)/lib/pkgconfig" >> $GITHUB_ENV
- name: Install OpenSSL (Windows)
if: runner.os == 'Windows'
run: |
choco install openssl --params='/InstallationPath:C:\OpenSSL\'
echo "OPENSSL_DIR=C:\OpenSSL" >> $env:GITHUB_ENV
echo "PKG_CONFIG_PATH=C:\OpenSSL\lib\pkgconfig" >> $env:GITHUB_ENV
- name: Run tests
run: cargo test --verbose
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
needs: determine-changes
if: >
needs.determine-changes.outputs.only_docs != 'true' &&
needs.determine-changes.outputs.only_tests != 'true'
strategy:
fail-fast: false
matrix:
include:
# Linux builds
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
asset_name: yek-x86_64-unknown-linux-gnu.tar.gz
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
asset_name: yek-aarch64-unknown-linux-gnu.tar.gz
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
asset_name: yek-x86_64-unknown-linux-musl.tar.gz
# macOS
- os: macos-latest
target: x86_64-apple-darwin
asset_name: yek-x86_64-apple-darwin.tar.gz
- os: macos-latest
target: aarch64-apple-darwin
asset_name: yek-aarch64-apple-darwin.tar.gz
# Windows
- os: windows-latest
target: x86_64-pc-windows-msvc
asset_name: yek-x86_64-pc-windows-msvc.zip
- os: windows-latest
target: aarch64-pc-windows-msvc
asset_name: yek-aarch64-pc-windows-msvc.zip
steps:
- uses: actions/checkout@v4
- name: Cache Cargo dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Install system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libssl-dev lcov
- name: Build
uses: ./.github/actions/build
id: build
with:
target: ${{ matrix.target }}
- name: Package binary (Unix)
if: runner.os != 'Windows'
shell: bash
run: |
mkdir -p release-artifacts
staging="yek-${{ matrix.target }}"
mkdir -p "$staging"
cp "${{ steps.build.outputs.binary_path }}" "$staging/"
tar czf "release-artifacts/${{ matrix.asset_name }}" "$staging"
[ -f "release-artifacts/${{ matrix.asset_name }}" ] || { echo "::error::No artifact"; exit 1; }
[ -s "release-artifacts/${{ matrix.asset_name }}" ] || { echo "::error::Artifact is empty"; exit 1; }
- name: Package binary (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path release-artifacts
$staging = "yek-${{ matrix.target }}"
New-Item -ItemType Directory -Force -Path $staging
Copy-Item "${{ steps.build.outputs.binary_path }}" $staging
7z a "release-artifacts\${{ matrix.asset_name }}" "$staging"
if (-not (Test-Path "release-artifacts\${{ matrix.asset_name }}")) {
Write-Error "No artifact"
exit 1
}
if ((Get-Item "release-artifacts\${{ matrix.asset_name }}").Length -eq 0) {
Write-Error "Artifact is empty"
exit 1
}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.target }}
path: release-artifacts/${{ matrix.asset_name }}
stress:
name: Stress ${{ matrix.target }}
needs: build
if: >
github.event_name == 'pull_request' &&
needs.determine-changes.outputs.only_docs != 'true' &&
needs.determine-changes.outputs.only_tests != 'true'
runs-on: ${{ matrix.os }}
concurrency:
group: ${{ github.workflow }}-stress-${{ matrix.target }}-${{ github.ref }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: macos-latest
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: build-${{ matrix.target }}
path: dist
- name: Extract and install binary
shell: bash
run: |
mkdir -p bin
if [[ "${{ runner.os }}" == "Windows" ]]; then
7z x "dist/yek-${{ matrix.target }}.zip" -obin
cp bin/yek-${{ matrix.target }}/yek.exe /c/Windows/System32/
else
tar xzf dist/yek-${{ matrix.target }}.tar.gz -C bin
chmod +x bin/yek-${{ matrix.target }}/yek
sudo cp bin/yek-${{ matrix.target }}/yek /usr/local/bin/
fi
- name: Checkout VSCode for stress example
uses: actions/checkout@v4
with:
repository: microsoft/vscode
path: vscode
fetch-depth: 1 # needed to make sure story is deep enough
- name: Run stress test
shell: bash
timeout-minutes: 1 # only 1 minute to serialize VSCode
working-directory: vscode
run: yek
benchmark:
name: Benchmark / ${{ matrix.benchmark_group.name }}
needs: build
if: >
github.event_name == 'pull_request' &&
needs.determine-changes.outputs.only_docs != 'true' &&
needs.determine-changes.outputs.only_tests != 'true'
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-benchmark-${{ matrix.benchmark_group.group }}-${{ github.ref }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
benchmark_group:
- group: SingleFile_ByteMode
name: Single File Byte Mode
- group: SingleFile_ByteMode_Large
name: Single File Byte Mode Large
- group: SingleFile_TokenMode_Large
name: Single File Token Mode Large
- group: MultipleFiles_Small
name: Multiple Files Small
- group: MultipleFiles_Medium
name: Multiple Files Medium
- group: MultipleFiles_Large
name: Multiple Files Large
- group: MultipleFiles_TokenMode
name: Multiple Files Token Mode
- group: CustomConfig
name: Custom Config
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@stable
- name: Run benchmarks
run: |
git fetch origin ${{ github.base_ref }}
git checkout ${{ github.base_ref }}
cargo bench --bench serialization --no-run
cargo bench --bench serialization -- --save-baseline ${{ github.base_ref }} '${{ matrix.benchmark_group.group }}/'
git checkout ${{ github.head_ref }}
cargo bench --bench serialization --no-run
cargo bench --bench serialization -- --baseline ${{ github.base_ref }} --noise-threshold 2 '${{ matrix.benchmark_group.group }}/' > benchmark_results.md
echo "## Benchmark Results for ${{ matrix.benchmark_group.name }}" >> $GITHUB_STEP_SUMMARY
cat benchmark_results.md >> $GITHUB_STEP_SUMMARY
- name: Upload benchmark results
uses: actions/upload-artifact@v4
with:
name: criterion-${{ matrix.benchmark_group.group }}-results
path: benchmark_results.md
release:
name: Release
needs: [test, lint, build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.event.base_ref, 'main')
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: dist
pattern: build-*
- name: Generate release notes
uses: orhun/git-cliff-action@v2
id: git-cliff
with:
config: cliff.toml
args: --current --strip header
env:
OUTPUT: CHANGES.md
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: dist/build-*/yek-*
body_path: CHANGES.md
tag_name: ${{ github.ref_name }}
publish:
name: Publish to crates.io
needs: [test, lint, build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.event.base_ref, 'main')
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.84.0"
- name: Publish
run: |
if cargo search --color=never yek | grep -q ${{ github.ref_name }}; then
echo "yek@${{ github.ref_name }} already published"
exit 0
fi
cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
coverage:
name: Code Coverage
needs: determine-changes
runs-on: ubuntu-latest
if: needs.determine-changes.outputs.only_docs != 'true'
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-Cinstrument-coverage"
LLVM_PROFILE_FILE: "yek-%p-%m.profraw"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed so we can check out base_ref below
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libssl-dev lcov
- name: Install grcov
run: cargo install grcov
# --- Base Branch Coverage ---
- name: Fetch and check out base branch
if: github.event_name == 'pull_request'
run: |
git fetch origin ${{ github.base_ref }}
git checkout ${{ github.base_ref }}
- name: Build + Test coverage on base
if: github.event_name == 'pull_request'
run: |
mkdir -p coverage-base
LLVM_PROFILE_FILE="coverage-base/yek-%p-%m.profraw" cargo test --profile coverage
grcov . \
--binary-path ./target/coverage/deps/ \
-s . \
-t lcov \
--branch \
--ignore-not-existing \
--ignore "/*" \
--ignore "tests/*" \
-o coverage-base/lcov.info
grcov . \
--binary-path ./target/coverage/deps/ \
-s . \
-t covdir \
--branch \
--ignore-not-existing \
--ignore "/*" \
--ignore "tests/*" \
-o coverage-base/coverage.json
# --- PR Branch Coverage ---
- name: Check out head branch (PR)
if: github.event_name == 'pull_request'
run: |
git checkout ${{ github.head_ref }}
- name: Build + Test coverage on PR
run: |
mkdir -p coverage
LLVM_PROFILE_FILE="coverage/yek-%p-%m.profraw" cargo test --profile coverage
grcov . \
--binary-path ./target/coverage/deps/ \
-s . \
-t lcov \
--branch \
--ignore-not-existing \
--ignore "/*" \
--ignore "tests/*" \
-o coverage/lcov.info
grcov . \
--binary-path ./target/coverage/deps/ \
-s . \
-t covdir \
--branch \
--ignore-not-existing \
--ignore "/*" \
--ignore "tests/*" \
-o coverage/coverage.json
- name: Compare coverage
if: github.event_name == 'pull_request'
run: |
# Check if base coverage file exists
if [ ! -f coverage-base/coverage.json ]; then
echo "No base branch coverage data found - this might be the first coverage run"
echo "PR branch coverage: $(jq -r '.coveragePercent' coverage/coverage.json)%"
exit 0
fi
# Extract line coverage from JSON files using jq
BASE_COV=$(jq -r '.coveragePercent' coverage-base/coverage.json)
PR_COV=$(jq -r '.coveragePercent' coverage/coverage.json)
echo "Base branch coverage: ${BASE_COV}%"
echo "PR branch coverage: ${PR_COV}%"
# Compare and fail if coverage decreased
check=$(awk -v base="$BASE_COV" -v pr="$PR_COV" 'BEGIN { if (pr < base) print 1; else print 0; }')
if [ "$check" -eq 1 ]; then
echo "Error: Coverage decreased from ${BASE_COV}% to ${PR_COV}%"
exit 1
else
echo "Coverage has not decreased."
fi
- name: Upload coverage reports
uses: actions/upload-artifact@v4
with:
name: coverage-reports
path: |
coverage/lcov.info
coverage-base/lcov.info