mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
ci: right-size pipelines, fix prerelease latest.json overwrite (#4582)
- build.yml: update latest.json only for stable release tags (alpha/beta/rc tags previously overwrote the stable pointer with release_type "stable"); drop the placeholder .asc files; build the Linux targets only on main pushes (tags/schedule/dispatch keep the full matrix); remove the unreachable --build clause and a needless full-history clone - ci.yml: event-scoped concurrency so merges stop cancelling the weekly scheduled run; drop the redundant skip-duplicate-actions gate job; run clippy before tests; trim the unused toolchain from the typos job - ci-docs-only.yml (new): satisfy the required "Test and Lint" check on docs-only PRs that ci.yml skips via paths-ignore - audit.yml: drop cargo-audit (cargo-deny advisories covers the same RustSec database); same event-scoped concurrency fix - docker.yml: job-level short-circuit for per-merge dev builds; send the Trivy SARIF to code scanning; unify the upload-artifact pin - performance-ab.yml: add concurrency; only re-run on labeled events when the added label is perf-ab - stagger the Sunday crons (build 01:00, audit 03:00, nix-flake-update 05:00, mint 06:00) - delete performance.yml: disabled since 2025-07; idle-server profiling, no benchmark baseline, stale ecstore package name
This commit is contained in:
@@ -35,15 +35,17 @@ on:
|
||||
- '.github/workflows/**'
|
||||
- 'scripts/security/check_workflow_pins.sh'
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Weekly on Sunday at midnight UTC
|
||||
- cron: '0 3 * * 0' # Weekly on Sunday 03:00 UTC (staggered after the midnight ci/build crons)
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Event-scoped groups: merges to main must not cancel the weekly scheduled
|
||||
# run (same rationale as ci.yml).
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name != 'schedule' }}
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -57,32 +59,9 @@ jobs:
|
||||
- name: Explain cancellation run
|
||||
run: echo "PR closed; this run only cancels older runs in the same concurrency group."
|
||||
|
||||
security-audit:
|
||||
name: Security Audit
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
||||
|
||||
- name: Install cargo-audit
|
||||
uses: taiki-e/install-action@bffeee26d4db9be238a4ea78d8826604ebcb594d # v2
|
||||
with:
|
||||
tool: cargo-audit
|
||||
|
||||
- name: Run security audit
|
||||
run: |
|
||||
cargo audit -D warnings --json | tee audit-results.json
|
||||
|
||||
- name: Upload audit results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: security-audit-results-${{ github.run_number }}
|
||||
path: audit-results.json
|
||||
retention-days: 30
|
||||
|
||||
# RustSec advisory scanning is covered by the `advisories` check of
|
||||
# cargo-deny below; a separate cargo-audit job would duplicate the same
|
||||
# database lookup with a second ignore list to maintain.
|
||||
cargo-deny:
|
||||
name: Cargo Deny
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
|
||||
+23
-13
@@ -21,6 +21,11 @@
|
||||
# 2. Upload binaries to OSS storage
|
||||
# 3. Trigger docker.yml to build and push images using the uploaded binaries
|
||||
#
|
||||
# Platform scope:
|
||||
# - Pushes to main (development builds) build the Linux targets only — they
|
||||
# feed the dev download channel and Docker dev images. Tags, the weekly
|
||||
# schedule and manual dispatch build the full platform matrix.
|
||||
#
|
||||
# Manual Parameters:
|
||||
# - build_docker: Build and push Docker images (default: true)
|
||||
# - platforms: Comma-separated platform IDs or 'all' (default: all)
|
||||
@@ -46,7 +51,7 @@ on:
|
||||
- ".gitignore"
|
||||
- ".dockerignore"
|
||||
schedule:
|
||||
- cron: "0 0 * * 0" # Weekly on Sunday at midnight UTC
|
||||
- cron: "0 1 * * 0" # Weekly on Sunday 01:00 UTC (staggered after the ci.yml midnight cron)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_docker:
|
||||
@@ -87,8 +92,6 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine build strategy
|
||||
id: check
|
||||
@@ -125,8 +128,7 @@ jobs:
|
||||
version="dev-${short_sha}"
|
||||
echo "🛠️ Development build detected"
|
||||
elif [[ "${{ github.event_name }}" == "schedule" ]] || \
|
||||
[[ "${{ github.event_name }}" == "workflow_dispatch" ]] || \
|
||||
[[ "${{ contains(github.event.head_commit.message, '--build') }}" == "true" ]]; then
|
||||
[[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
# Scheduled or manual build
|
||||
should_build=true
|
||||
build_type="development"
|
||||
@@ -150,6 +152,7 @@ jobs:
|
||||
# Build RustFS binaries
|
||||
prepare-platform-matrix:
|
||||
name: Prepare Platform Matrix
|
||||
needs: build-check
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.select.outputs.matrix }}
|
||||
@@ -167,6 +170,18 @@ jobs:
|
||||
selected="all"
|
||||
fi
|
||||
|
||||
# Per-merge development builds only feed the dev download channel
|
||||
# and the Docker dev images, which consume the Linux binaries; at
|
||||
# the usual merge cadence most per-merge builds are cancelled by the
|
||||
# next merge anyway. macOS and Windows stay covered by tag builds,
|
||||
# the weekly scheduled build and manual dispatch.
|
||||
if [[ "${selected}" == "all" \
|
||||
&& "${{ github.event_name }}" == "push" \
|
||||
&& "${{ needs.build-check.outputs.build_type }}" == "development" ]]; then
|
||||
selected="linux-x86_64-musl,linux-aarch64-musl,linux-x86_64-gnu,linux-aarch64-gnu"
|
||||
echo "Development (main push) build: restricting to Linux targets"
|
||||
fi
|
||||
|
||||
all='{"include":[
|
||||
{"target_id":"linux-x86_64-musl","os":"sm-standard-2","target":"x86_64-unknown-linux-musl","cross":false,"platform":"linux","rustflags":""},
|
||||
{"target_id":"linux-aarch64-musl","os":"sm-standard-2","target":"aarch64-unknown-linux-musl","cross":true,"platform":"linux","rustflags":""},
|
||||
@@ -783,12 +798,6 @@ jobs:
|
||||
sha512sum *.zip > SHA512SUMS
|
||||
fi
|
||||
|
||||
# Create signature placeholder files
|
||||
for file in *.zip; do
|
||||
echo "# Signature for $file" > "${file}.asc"
|
||||
echo "# GPG signature will be added in future versions" >> "${file}.asc"
|
||||
done
|
||||
|
||||
cd ..
|
||||
python3 scripts/security/generate_release_supply_chain_assets.py \
|
||||
--asset-dir ./release-assets \
|
||||
@@ -826,11 +835,12 @@ jobs:
|
||||
|
||||
echo "✅ All assets uploaded successfully"
|
||||
|
||||
# Update latest.json for stable releases only
|
||||
# Update latest.json for stable releases only: prerelease tags (alpha/beta/
|
||||
# rc) must never overwrite the stable version pointer.
|
||||
update-latest-version:
|
||||
name: Update Latest Version
|
||||
needs: [ build-check, upload-release-assets ]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
if: startsWith(github.ref, 'refs/tags/') && needs.build-check.outputs.build_type == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update latest.json
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Copyright 2026 RustFS Team
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Companion to ci.yml for the required "Test and Lint" status check.
|
||||
#
|
||||
# ci.yml skips docs-only pull requests via paths-ignore, but the branch
|
||||
# ruleset requires a check named "Test and Lint" — without this workflow a
|
||||
# docs-only PR would wait on that check forever. This workflow triggers on
|
||||
# exactly the paths ci.yml ignores and reports an instant success under the
|
||||
# same job name. Mixed PRs trigger both workflows and the real check still
|
||||
# gates: a required check with any failing run blocks the merge.
|
||||
# https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks
|
||||
#
|
||||
# Keep the paths list below in sync with the pull_request paths-ignore list
|
||||
# in ci.yml.
|
||||
|
||||
name: Continuous Integration (docs only)
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened, synchronize, reopened ]
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- "**.md"
|
||||
- "docs/**"
|
||||
- "deploy/**"
|
||||
- "scripts/dev_*.sh"
|
||||
- "scripts/probe.sh"
|
||||
- "LICENSE*"
|
||||
- ".gitignore"
|
||||
- ".dockerignore"
|
||||
- "README*"
|
||||
- "**/*.png"
|
||||
- "**/*.jpg"
|
||||
- "**/*.svg"
|
||||
- ".github/workflows/build.yml"
|
||||
- ".github/workflows/docker.yml"
|
||||
- ".github/workflows/audit.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-and-lint:
|
||||
name: Test and Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Satisfy required check for docs-only changes
|
||||
run: echo "Docs-only change — code CI is skipped by paths-ignore; reporting success for the required 'Test and Lint' check."
|
||||
+31
-54
@@ -33,10 +33,11 @@ on:
|
||||
- ".github/workflows/build.yml"
|
||||
- ".github/workflows/docker.yml"
|
||||
- ".github/workflows/audit.yml"
|
||||
- ".github/workflows/performance.yml"
|
||||
pull_request:
|
||||
types: [ opened, synchronize, reopened, closed ]
|
||||
branches: [ main ]
|
||||
# Keep this list in sync with the `paths` list in ci-docs-only.yml, which
|
||||
# reports the required "Test and Lint" check for PRs skipped here.
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "docs/**"
|
||||
@@ -53,7 +54,6 @@ on:
|
||||
- ".github/workflows/build.yml"
|
||||
- ".github/workflows/docker.yml"
|
||||
- ".github/workflows/audit.yml"
|
||||
- ".github/workflows/performance.yml"
|
||||
merge_group:
|
||||
types: [ checks_requested ]
|
||||
schedule:
|
||||
@@ -63,9 +63,13 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Concurrency groups are scoped per event so different triggers never cancel
|
||||
# each other: PR pushes cancel the previous run of that PR, main pushes keep
|
||||
# latest-wins semantics among themselves, and scheduled runs always complete
|
||||
# (a shared group used to let every merge kill the weekly scheduled run).
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name != 'schedule' }}
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -81,33 +85,12 @@ jobs:
|
||||
- name: Explain cancellation run
|
||||
run: echo "PR closed; this run only cancels older runs in the same concurrency group."
|
||||
|
||||
skip-check:
|
||||
name: Skip Duplicate Actions
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
permissions:
|
||||
actions: write
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
steps:
|
||||
- name: Skip duplicate actions
|
||||
id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@f75f66ce1886f00957d99748a42c724f4330bdcf # v5
|
||||
with:
|
||||
concurrent_skipping: "same_content_newer"
|
||||
cancel_others: true
|
||||
paths_ignore: '["*.md", "docs/**", "deploy/**"]'
|
||||
do_not_skip: '["workflow_dispatch", "schedule", "merge_group", "release", "push"]'
|
||||
|
||||
typos:
|
||||
name: Typos
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
||||
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
||||
- name: Typos check with custom config file
|
||||
uses: crate-ci/typos@37bb98842b0d8c4ffebdb75301a13db0267cef89 # master
|
||||
|
||||
@@ -115,8 +98,7 @@ jobs:
|
||||
# ~1 minute instead of waiting for the full test job.
|
||||
quick-checks:
|
||||
name: Quick Checks
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
@@ -148,8 +130,7 @@ jobs:
|
||||
|
||||
test-and-lint:
|
||||
name: Test and Lint
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: sm-standard-4
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
@@ -166,6 +147,12 @@ jobs:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
cache-save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
# Clippy runs before the test pass: lint failures are the most common
|
||||
# CI-only breakage and should surface in minutes, not after 20+ minutes
|
||||
# of tests.
|
||||
- name: Run clippy lints
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cargo nextest run --all --exclude e2e_test
|
||||
@@ -179,13 +166,9 @@ jobs:
|
||||
cargo nextest run -p rustfs-ecstore --lib \
|
||||
-E 'test(data_movement) or test(rebalance) or test(decommission) or test(source_cleanup) or test(delete_marker)'
|
||||
|
||||
- name: Run clippy lints
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
|
||||
test-and-lint-rio-v2:
|
||||
name: Test and Lint (rio-v2)
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: sm-standard-4
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
@@ -202,18 +185,17 @@ jobs:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
cache-save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Run rio-v2 clippy lints
|
||||
run: cargo clippy -p rustfs -p rustfs-ecstore --all-targets --features rio-v2 -- -D warnings
|
||||
|
||||
- name: Run rio-v2 feature tests
|
||||
run: |
|
||||
cargo nextest run -p rustfs -p rustfs-ecstore --features rio-v2
|
||||
cargo test -p rustfs --doc --features rio-v2
|
||||
|
||||
- name: Run rio-v2 clippy lints
|
||||
run: cargo clippy -p rustfs -p rustfs-ecstore --all-targets --features rio-v2 -- -D warnings
|
||||
|
||||
test-and-lint-protocols:
|
||||
name: "Test and Lint (${{ matrix.features.name }})"
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: sm-standard-4
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
@@ -238,18 +220,17 @@ jobs:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
cache-save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Run tests with ${{ matrix.features.name }}
|
||||
run: |
|
||||
cargo nextest run -p rustfs -p rustfs-protocols ${{ matrix.features.flags }}
|
||||
|
||||
- name: Run clippy with ${{ matrix.features.name }}
|
||||
run: |
|
||||
cargo clippy -p rustfs -p rustfs-protocols --all-targets ${{ matrix.features.flags }} -- -D warnings
|
||||
|
||||
- name: Run tests with ${{ matrix.features.name }}
|
||||
run: |
|
||||
cargo nextest run -p rustfs -p rustfs-protocols ${{ matrix.features.flags }}
|
||||
|
||||
build-rustfs-debug-binary:
|
||||
name: Build RustFS Debug Binary
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: sm-standard-4
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
@@ -279,8 +260,7 @@ jobs:
|
||||
|
||||
build-rustfs-debug-binary-rio-v2:
|
||||
name: Build RustFS Debug Binary (rio-v2)
|
||||
needs: skip-check
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
if: github.event_name != 'pull_request' || github.event.action != 'closed'
|
||||
runs-on: sm-standard-4
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
@@ -310,8 +290,7 @@ jobs:
|
||||
|
||||
e2e-tests:
|
||||
name: End-to-End Tests
|
||||
needs: [ skip-check, build-rustfs-debug-binary ]
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
needs: [ build-rustfs-debug-binary ]
|
||||
runs-on: sm-standard-2
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
@@ -370,8 +349,7 @@ jobs:
|
||||
|
||||
e2e-tests-rio-v2:
|
||||
name: End-to-End Tests (rio-v2)
|
||||
needs: [ skip-check, build-rustfs-debug-binary-rio-v2 ]
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
needs: [ build-rustfs-debug-binary-rio-v2 ]
|
||||
runs-on: sm-standard-2
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
@@ -417,8 +395,7 @@ jobs:
|
||||
|
||||
s3-implemented-tests:
|
||||
name: S3 Implemented Tests
|
||||
needs: [ skip-check, build-rustfs-debug-binary, e2e-tests ]
|
||||
if: needs.skip-check.outputs.should_skip != 'true'
|
||||
needs: [ build-rustfs-debug-binary, e2e-tests ]
|
||||
runs-on: sm-standard-4
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
|
||||
@@ -70,9 +70,19 @@ env:
|
||||
DOCKER_PLATFORMS: linux/amd64,linux/arm64
|
||||
|
||||
jobs:
|
||||
# Check if we should build Docker images
|
||||
# Check if we should build Docker images.
|
||||
# Short-circuit at job level so per-merge development builds (workflow_run
|
||||
# from a push to main) skip the whole run without spawning a checkout job:
|
||||
# images are only published for tag builds — build.yml push triggers cover
|
||||
# only main and tags, so a non-main head_branch is a tag name — and for
|
||||
# manual dispatch.
|
||||
build-check:
|
||||
name: Docker Build Check
|
||||
if: >-
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.workflow_run.conclusion == 'success' &&
|
||||
github.event.workflow_run.event == 'push' &&
|
||||
github.event.workflow_run.head_branch != 'main')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_build: ${{ steps.check.outputs.should_build }}
|
||||
@@ -86,7 +96,6 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# For workflow_run events, checkout the specific commit that triggered the workflow
|
||||
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
|
||||
|
||||
@@ -421,6 +430,9 @@ jobs:
|
||||
needs: [ build-check, build-docker ]
|
||||
if: needs.build-check.outputs.should_build == 'true' && needs.build-check.outputs.should_push == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -450,9 +462,16 @@ jobs:
|
||||
severity: CRITICAL,HIGH
|
||||
exit-code: "0"
|
||||
|
||||
# Surface findings in the Security tab; an artifact alone is write-only
|
||||
# reporting nobody reviews.
|
||||
- name: Upload scan results to code scanning
|
||||
uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
with:
|
||||
sarif_file: trivy-${{ matrix.variant }}.sarif
|
||||
category: container-image-${{ matrix.variant }}
|
||||
|
||||
- name: Upload container scan report
|
||||
# actions/upload-artifact v7.0.1
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: container-image-scan-${{ matrix.variant }}
|
||||
path: trivy-${{ matrix.variant }}.sarif
|
||||
|
||||
@@ -50,8 +50,9 @@ on:
|
||||
required: false
|
||||
default: "minio/mint:edge"
|
||||
schedule:
|
||||
# Weekly, after the Sunday s3-tests full sweep.
|
||||
- cron: "0 4 * * 0"
|
||||
# Weekly, after the Sunday s3-tests full sweep (starts 02:00 UTC, up to
|
||||
# 3h) has finished, so the two never contend for the same runner pool.
|
||||
- cron: "0 6 * * 0"
|
||||
|
||||
env:
|
||||
S3_ACCESS_KEY: rustfsadmin
|
||||
|
||||
@@ -17,7 +17,7 @@ name: Update Nix Flake
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Weekly on Sundays
|
||||
- cron: '0 5 * * 0' # Weekly on Sunday 05:00 UTC (staggered after the midnight ci/build crons)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@@ -46,6 +46,13 @@ permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
# Per-PR: a new push cancels the previous (up to 90-minute) A/B run instead of
|
||||
# stacking them. Nightly schedule and manual dispatch get a unique group and
|
||||
# always run to completion.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUST_BACKTRACE: 1
|
||||
@@ -53,11 +60,14 @@ env:
|
||||
jobs:
|
||||
warp-ab:
|
||||
name: Warp A/B budget gate
|
||||
# Opt-in on PRs: only run when the `perf-ab` label is present. Always run on
|
||||
# schedule / manual dispatch.
|
||||
# Opt-in on PRs: only run when the `perf-ab` label is present, and for
|
||||
# `labeled` events only when the label being added is `perf-ab` itself —
|
||||
# adding an unrelated label to an opted-in PR must not re-run the gate.
|
||||
# Always run on schedule / manual dispatch.
|
||||
if: >-
|
||||
github.event_name != 'pull_request' ||
|
||||
contains(github.event.pull_request.labels.*.name, 'perf-ab')
|
||||
(contains(github.event.pull_request.labels.*.name, 'perf-ab') &&
|
||||
(github.event.action != 'labeled' || github.event.label.name == 'perf-ab'))
|
||||
runs-on: sm-standard-2
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
# Copyright 2024 RustFS Team
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
name: Performance Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
- "**/Cargo.lock"
|
||||
- ".github/workflows/performance.yml"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
profile_duration:
|
||||
description: "Profiling duration in seconds"
|
||||
required: false
|
||||
default: "120"
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUST_BACKTRACE: 1
|
||||
|
||||
jobs:
|
||||
performance-profile:
|
||||
name: Performance Profiling
|
||||
runs-on: sm-standard-2
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
||||
|
||||
- name: Setup Rust environment
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
rust-version: nightly
|
||||
cache-shared-key: perf-${{ hashFiles('**/Cargo.lock') }}
|
||||
cache-save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install additional nightly components
|
||||
run: rustup component add llvm-tools-preview
|
||||
|
||||
- name: Install samply profiler
|
||||
uses: taiki-e/cache-cargo-install-action@7447f04c51f2ba27ca35e7f1e28fab848c5b3ba7 # v2
|
||||
with:
|
||||
tool: samply
|
||||
|
||||
- name: Configure kernel for profiling
|
||||
run: echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid
|
||||
|
||||
- name: Prepare test environment
|
||||
run: |
|
||||
# Create test volumes
|
||||
for i in {0..4}; do
|
||||
mkdir -p ./target/volume/test$i
|
||||
done
|
||||
|
||||
# Set environment variables
|
||||
echo "RUSTFS_VOLUMES=./target/volume/test{0...4}" >> $GITHUB_ENV
|
||||
echo "RUST_LOG=rustfs=info,ecstore=info,s3s=info,iam=info,rustfs-obs=info" >> $GITHUB_ENV
|
||||
|
||||
- name: Verify console static assets
|
||||
run: |
|
||||
# Console static assets are already embedded in the repository
|
||||
echo "Console static assets size: $(du -sh rustfs/static/)"
|
||||
echo "Console static assets are embedded via rust-embed, no external download needed"
|
||||
|
||||
- name: Build with profiling optimizations
|
||||
run: |
|
||||
RUSTFLAGS="-C force-frame-pointers=yes -C debug-assertions=off --cfg tokio_unstable" \
|
||||
cargo +nightly build --profile profiling -p rustfs --bins
|
||||
|
||||
- name: Run performance profiling
|
||||
id: profiling
|
||||
run: |
|
||||
DURATION="${{ github.event.inputs.profile_duration || '120' }}"
|
||||
echo "Running profiling for ${DURATION} seconds..."
|
||||
|
||||
timeout "${DURATION}s" samply record \
|
||||
--output samply-profile.json \
|
||||
./target/profiling/rustfs ${RUSTFS_VOLUMES} || true
|
||||
|
||||
if [ -f "samply-profile.json" ]; then
|
||||
echo "profile_generated=true" >> $GITHUB_OUTPUT
|
||||
echo "Profile generated successfully"
|
||||
else
|
||||
echo "profile_generated=false" >> $GITHUB_OUTPUT
|
||||
echo "::warning::Profile data not generated"
|
||||
fi
|
||||
|
||||
- name: Upload profile data
|
||||
if: steps.profiling.outputs.profile_generated == 'true'
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: performance-profile-${{ github.run_number }}
|
||||
path: samply-profile.json
|
||||
retention-days: 30
|
||||
|
||||
benchmark:
|
||||
name: Benchmark Tests
|
||||
runs-on: sm-standard-2
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
||||
|
||||
- name: Setup Rust environment
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
rust-version: stable
|
||||
cache-shared-key: bench-${{ hashFiles('**/Cargo.lock') }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
cache-save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Run benchmarks
|
||||
run: |
|
||||
cargo bench --package ecstore --bench comparison_benchmark -- --output-format json | \
|
||||
tee benchmark-results.json
|
||||
|
||||
- name: Upload benchmark results
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: benchmark-results-${{ github.run_number }}
|
||||
path: benchmark-results.json
|
||||
retention-days: 7
|
||||
Reference in New Issue
Block a user