Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3ff3193
fix(e2e): send SSE-C key MD5 in Base64 per S3 spec
andybrown668 Mar 12, 2026
2bd6215
e2e: always build rustfs once and only once
andybrown668 Mar 13, 2026
ba5295c
refactor(e2e): add run_test_* bodies for unified KMS runner
andybrown668 Mar 12, 2026
1dc401f
chore(e2e): ensure awscurl for e2e tests and improve missing-tool errors
andybrown668 Mar 12, 2026
e0178cd
feat(rio): add ExactLengthReader for decrypted GET body length valida…
andybrown668 Mar 16, 2026
8fdcb8b
feat(kms): use UTC timestamps and encryption context for DEK
andybrown668 Mar 16, 2026
c9ed1ec
feat(storage): SSE encryption context, ExactLengthReader, metadata fi…
andybrown668 Mar 16, 2026
477d08b
feat(app): SSE-S3 key ID semantics, metadata filter, versioning, encr…
andybrown668 Mar 16, 2026
b44a4a7
fix(ecstore): invalidate file cache after write_all
andybrown668 Mar 16, 2026
bd2e9d1
feat(policy): allow Resource "*" as IAM shorthand for all resources
andybrown668 Mar 16, 2026
459cce5
test(e2e): server env, process group, KMS key format, vault seed
andybrown668 Mar 16, 2026
5ec19a5
test(e2e): use shared env and un-ignore tests
andybrown668 Mar 16, 2026
277a584
ci(build): restrict fork builds to x86_64-unknown-linux-gnu
andybrown668 Mar 16, 2026
a10b5e1
ci: install protoc via direct download instead of arduino/setup-protoc
andybrown668 Mar 16, 2026
d80eeb5
ci: skip cargo-nextest install when already at pinned version
andybrown668 Mar 16, 2026
f006ab6
ci: set CARGO_BUILD_JOBS from runner (labs-large → 40)
andybrown668 Apr 6, 2026
746aa40
ci: add lab sccache env script and source in setup action
andybrown668 Apr 15, 2026
72fbafb
ci: add workflow for lab sccache build benchmark
andybrown668 Apr 15, 2026
53edac8
chore(scripts): add run-on-runners SSH helper
andybrown668 Apr 15, 2026
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
41 changes: 40 additions & 1 deletion .config/make/check.mak
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,46 @@ warn-%:
}

# For checking dependencies use check-<dep-name> or warn-<dep-name>
.PHONY: core-deps fmt-deps test-deps
.PHONY: core-deps fmt-deps test-deps check-awscurl install-awscurl ensure-awscurl
core-deps: check-cargo ## Check core dependencies
fmt-deps: check-rustfmt ## Check lint and formatting dependencies
test-deps: warn-cargo-nextest ## Check tests dependencies

# awscurl: required for e2e tests that call admin/HTTP endpoints (e.g. quota_test)
# Check only; use ensure-awscurl to install if missing.
check-awscurl:
@if [ -n "$${AWSCURL_PATH:-}" ] && [ -x "$${AWSCURL_PATH:-}" ]; then \
echo "✅ awscurl found at $${AWSCURL_PATH}"; \
elif command -v awscurl >/dev/null 2>&1; then \
echo "✅ awscurl found ($$(command -v awscurl))"; \
else \
echo >&2 "❌ awscurl is not installed and AWSCURL_PATH is not set."; \
echo >&2 " Install with: make install-awscurl"; \
exit 1; \
fi

# Install awscurl: prefer pipx (avoids externally-managed-environment); fallback to pip --user.
install-awscurl:
@if [ -n "$${AWSCURL_PATH:-}" ] && [ -x "$${AWSCURL_PATH:-}" ]; then \
echo "✅ awscurl already available at $${AWSCURL_PATH}"; \
elif command -v awscurl >/dev/null 2>&1; then \
echo "✅ awscurl already installed ($$(command -v awscurl))"; \
else \
echo "Installing awscurl..."; \
if command -v pipx >/dev/null 2>&1 && pipx install awscurl; then \
:; \
elif command -v pip3 >/dev/null 2>&1 && pip3 install --user awscurl; then \
:; \
elif command -v pip >/dev/null 2>&1 && pip install --user awscurl; then \
:; \
else \
echo >&2 "❌ Could not install awscurl."; \
echo >&2 " On externally-managed Python, use: pipx install awscurl"; \
echo >&2 " (Install pipx if needed: e.g. apt install pipx && pipx ensurepath)"; \
exit 1; \
fi; \
echo "✅ awscurl installed ($$(command -v awscurl))"; \
fi

# Idempotent: ensure awscurl is available, installing if missing.
ensure-awscurl: install-awscurl
14 changes: 12 additions & 2 deletions .config/make/tests.mak
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ test: core-deps test-deps ## Run all tests
cargo test --all --doc

.PHONY: e2e-server
e2e-server: ## Run e2e-server tests
e2e-server: ensure-awscurl ## Run e2e-server tests
sh $(shell pwd)/scripts/run.sh

.PHONY: probe-e2e
probe-e2e: ## Probe e2e tests
probe-e2e: ensure-awscurl ## Probe e2e tests
sh $(shell pwd)/scripts/probe.sh

# E2E tests start a RustFS server each; they must run single-threaded so one test
# does not kill another's server (cleanup kills all rustfs processes).
# The e2e test setup builds rustfs once and only once per run (see common::rustfs_binary_path),
# so you can run with cargo test -p e2e_test or make e2e-test.
# RUSTFS_BUILD_FEATURES=ftps ensures the binary is built with FTPS for protocol tests.
.PHONY: e2e-test
e2e-test: core-deps test-deps ## Run e2e_test crate (single-threaded)
@echo "🧪 Running e2e tests (single-threaded)..."
RUSTFS_BUILD_FEATURES=ftps cargo test -p e2e_test -- --nocapture --test-threads=1
98 changes: 93 additions & 5 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,41 @@ inputs:
runs:
using: "composite"
steps:
# Workflow env cannot use runner context; set parallelism here so cargo respects CARGO_BUILD_JOBS.
# labs-large runners get 40 jobs; all others keep the workflow default (2).
- name: Set CARGO_BUILD_JOBS from runner (labs-large → 40)
shell: bash
env:
RUNNER_JSON: ${{ toJson(runner) }}
run: |
set -euo pipefail
jobs=2
if [[ "${RUNNER_JSON}" == *labs-large* ]]; then
jobs=40
elif [[ "${RUNNER_LABELS:-}" == *labs-large* ]]; then
jobs=40
else
for f in "${RUNNER_HOME:-}/.runner" "${HOME}/actions-runner/.runner" "/home/runner/actions-runner/.runner"; do
[ -n "${f:-}" ] || continue
[ -f "$f" ] || continue
if grep -q 'labs-large' "$f" 2>/dev/null; then
jobs=40
break
fi
done
fi
echo "CARGO_BUILD_JOBS=$jobs" >> "$GITHUB_ENV"
echo "Set CARGO_BUILD_JOBS=$jobs"

- name: Normalize sccache wrapper env
shell: bash
run: |
set -euo pipefail
if [[ -f scripts/lab-sccache-env.sh ]]; then
# shellcheck disable=SC1091
source scripts/lab-sccache-env.sh
fi

- name: Install system dependencies (Ubuntu)
if: runner.os == 'Linux'
shell: bash
Expand All @@ -53,13 +88,55 @@ runs:
musl-tools \
build-essential \
pkg-config \
libssl-dev
libssl-dev \
unzip

- name: Install protoc
uses: arduino/setup-protoc@v3
with:
version: "33.1"
repo-token: ${{ inputs.github-token }}
shell: bash
run: |
set -e
PROTOC_VERSION="33.1"
BASE_URL="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}"
ARCH=$(uname -m)
case "$RUNNER_OS" in
Linux)
case "$ARCH" in
x86_64) SUFFIX="linux-x86_64" ;;
aarch64) SUFFIX="linux-aarch_64" ;;
*) echo "Unsupported arch: $ARCH"; exit 1 ;;
esac
echo "Installing protoc ${PROTOC_VERSION} (${SUFFIX})..."
curl -sSL -o /tmp/protoc.zip "${BASE_URL}/protoc-${PROTOC_VERSION}-${SUFFIX}.zip"
sudo unzip -q -o /tmp/protoc.zip -d /usr/local bin/protoc 'include/*'
sudo chmod +x /usr/local/bin/protoc
rm /tmp/protoc.zip
;;
macOS)
case "$ARCH" in
x86_64) SUFFIX="osx-x86_64" ;;
arm64) SUFFIX="osx-aarch_64" ;;
*) echo "Unsupported arch: $ARCH"; exit 1 ;;
esac
echo "Installing protoc ${PROTOC_VERSION} (${SUFFIX})..."
curl -sSL -o /tmp/protoc.zip "${BASE_URL}/protoc-${PROTOC_VERSION}-${SUFFIX}.zip"
sudo unzip -q -o /tmp/protoc.zip -d /usr/local bin/protoc 'include/*'
sudo chmod +x /usr/local/bin/protoc
rm /tmp/protoc.zip
;;
Windows)
echo "Installing protoc ${PROTOC_VERSION} (win64)..."
curl -sSL -o "$RUNNER_TEMP/protoc.zip" "${BASE_URL}/protoc-${PROTOC_VERSION}-win64.zip"
unzip -q -o "$RUNNER_TEMP/protoc.zip" -d "$RUNNER_TEMP/protoc"
echo "$RUNNER_TEMP/protoc/bin" >> "$GITHUB_PATH"
echo "PATH=$RUNNER_TEMP/protoc/bin:$PATH" >> "$GITHUB_ENV"
rm "$RUNNER_TEMP/protoc.zip"
"$RUNNER_TEMP/protoc/bin/protoc.exe" --version
exit 0
;;
*)
echo "Unsupported OS: $RUNNER_OS"; exit 1 ;;
esac
protoc --version

- name: Install flatc
uses: Nugine/setup-flatc@v1
Expand All @@ -81,7 +158,18 @@ runs:
if: inputs.install-cross-tools == 'true'
uses: taiki-e/install-action@cargo-zigbuild

- name: Check cargo-nextest
id: check_nextest
shell: bash
run: |
NEED_INSTALL="true"
if command -v cargo-nextest &>/dev/null; then
NEED_INSTALL="false"
fi
echo "need_install=${NEED_INSTALL}" >> "$GITHUB_OUTPUT"

- name: Install cargo-nextest
if: steps.check_nextest.outputs.need_install != 'false'
uses: taiki-e/install-action@cargo-nextest

- name: Setup Rust cache
Expand Down
24 changes: 21 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ jobs:
version: ${{ steps.check.outputs.version }}
short_sha: ${{ steps.check.outputs.short_sha }}
is_prerelease: ${{ steps.check.outputs.is_prerelease }}
build_matrix: ${{ steps.matrix.outputs.build_matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
Expand Down Expand Up @@ -143,8 +144,16 @@ jobs:
echo " - Short SHA: $short_sha"
echo " - Is prerelease: $is_prerelease"

# Build RustFS binaries
- name: Set build matrix (forks only)
id: matrix
if: github.repository != 'rustfs/rustfs'
run: |
matrix='{"include":[{"target_id":"linux-x86_64-gnu","os":"ubicloud-standard-2","target":"x86_64-unknown-linux-gnu","cross":false,"platform":"linux","rustflags":""}]}'
echo "build_matrix=${matrix}" >> "$GITHUB_OUTPUT"

# Build RustFS binaries (upstream: selects platforms; forks skip this job and use build-check matrix)
prepare-platform-matrix:
if: github.repository == 'rustfs/rustfs'
name: Prepare Platform Matrix
runs-on: ubicloud-standard-2
outputs:
Expand All @@ -157,6 +166,15 @@ jobs:
run: |
set -euo pipefail

# Forks: only build x86_64-unknown-linux-gnu. Upstream (rustfs/rustfs) uses platforms input or all.
if [[ "${{ github.repository }}" != "rustfs/rustfs" ]]; then
matrix='{"include":[{"target_id":"linux-x86_64-gnu","os":"ubicloud-standard-2","target":"x86_64-unknown-linux-gnu","cross":false,"platform":"linux","rustflags":""}]}'
echo "selected=fork" >> "$GITHUB_OUTPUT"
echo "matrix=${matrix}" >> "$GITHUB_OUTPUT"
echo "Selected platforms: fork (x86_64-unknown-linux-gnu only)"
exit 0
fi

selected="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.platforms || 'all' }}"
selected="$(echo "${selected}" | tr -d '[:space:]')"
if [[ -z "${selected}" ]]; then
Expand Down Expand Up @@ -200,14 +218,14 @@ jobs:
build-rustfs:
name: Build RustFS
needs: [ build-check, prepare-platform-matrix ]
if: needs.build-check.outputs.should_build == 'true' && needs.prepare-platform-matrix.result == 'success'
if: needs.build-check.outputs.should_build == 'true' && (needs.prepare-platform-matrix.result == 'success' || (github.repository != 'rustfs/rustfs' && needs.prepare-platform-matrix.result == 'skipped'))
runs-on: ${{ matrix.os }}
timeout-minutes: 60
env:
RUSTFLAGS: ${{ matrix.rustflags }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare-platform-matrix.outputs.matrix) }}
matrix: ${{ fromJson(needs.build-check.outputs.build_matrix || needs.prepare-platform-matrix.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ on:
- "**/*.png"
- "**/*.jpg"
- "**/*.svg"
- ".github/workflows/build.yml"
- ".github/workflows/docker.yml"
- ".github/workflows/audit.yml"
- ".github/workflows/performance.yml"
Expand All @@ -49,7 +48,6 @@ on:
- "**/*.png"
- "**/*.jpg"
- "**/*.svg"
- ".github/workflows/build.yml"
- ".github/workflows/docker.yml"
- ".github/workflows/audit.yml"
- ".github/workflows/performance.yml"
Expand All @@ -67,6 +65,7 @@ concurrency:
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
# Default for jobs that do not run ./.github/actions/setup. Setup sets GITHUB_ENV to 40 when the runner has label labs-large.
CARGO_BUILD_JOBS: 2

jobs:
Expand Down Expand Up @@ -153,9 +152,10 @@ jobs:
- name: Build debug binary
run: |
touch rustfs/build.rs
cargo build -p rustfs --bins --jobs 2
cargo build -p rustfs --bins

- name: Upload debug binary
if: github.repository == 'rustfs/rustfs'
uses: actions/upload-artifact@v6
with:
name: rustfs-debug-binary
Expand All @@ -166,7 +166,7 @@ jobs:
e2e-tests:
name: End-to-End Tests
needs: [ skip-check, build-rustfs-debug-binary ]
if: needs.skip-check.outputs.should_skip != 'true'
if: needs.skip-check.outputs.should_skip != 'true' && github.repository == 'rustfs/rustfs'
runs-on: ubicloud-standard-2
timeout-minutes: 30
steps:
Expand Down Expand Up @@ -203,7 +203,7 @@ jobs:
./scripts/e2e-run.sh ./target/debug/rustfs /tmp/rustfs

- name: Upload test logs
if: failure()
if: failure() && github.repository == 'rustfs/rustfs'
uses: actions/upload-artifact@v6
with:
name: e2e-test-logs-${{ github.run_number }}
Expand All @@ -213,7 +213,7 @@ jobs:
s3-implemented-tests:
name: S3 Implemented Tests
needs: [ skip-check, build-rustfs-debug-binary ]
if: needs.skip-check.outputs.should_skip != 'true'
if: needs.skip-check.outputs.should_skip != 'true' && github.repository == 'rustfs/rustfs'
runs-on: ubicloud-standard-4
timeout-minutes: 60
steps:
Expand All @@ -238,7 +238,7 @@ jobs:
./scripts/s3-tests/run.sh

- name: Upload s3 test artifacts
if: always()
if: always() && github.repository == 'rustfs/rustfs'
uses: actions/upload-artifact@v6
with:
name: s3tests-implemented-${{ github.run_number }}
Expand Down
Loading