Files
zot/.github/workflows/gc-stress-test.yaml
Benoit Tigeot d97953f101 Pin actions and tighten workflow permissions (#3954)
* ci: Reduce chance of installing corrupt packages

See: https://dev.to/hsbt/should-rubygemsbundler-have-a-cooldown-feature-40cp
Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: prevent credential leakage from checkout steps

Add `persist-credentials: false` to all `actions/checkout` calls across
22 workflow files. Without this, the GitHub token used for checkout is
written into `.git/config` and remains accessible to all subsequent steps
and any uploaded artifacts (artipacked finding).

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: prevent template injection from github context in run steps

`${{ github.* }}` expressions used directly inside `run:` blocks are
expanded before the shell sees them. A crafted value (e.g. a tag name
containing shell metacharacters) would execute arbitrary code.

Move the values into `env:` variables (e.g. GITHUB_EVENT_RELEASE_TAG_NAME,
GITHUB_ACTOR) and reference them as `${VAR}` in the shell, so the runtime
never interprets them as code (template-injection finding).

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: prevent injection in yq commands via release tag name

`${{ github.event.release.tag_name }}` was interpolated directly into
yq `cmd:` inputs. A crafted tag name could inject shell commands since
the expression is expanded before the action runs. Use yq's `strenv()`
with an `env:` variable instead so the value is always treated as data.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: pin all GitHub Actions to full commit SHAs

Actions pinned to mutable tags (e.g. @v6, @main) can change under us if
the upstream repo is compromised or tags are moved, enabling supply-chain
attacks. Pinning to the full 40-char commit SHA locks the exact code that
runs. Version tags are preserved as inline comments (e.g. # v6.0.2) for
readability and Dependabot compatibility.

Used `pinact` for standard tagged versions; remaining branch-based
references (mikefarah/yq, jlumbroso/free-disk-space,
project-stacker/stacker-build-push-action, aquasecurity/trivy-action)
resolved manually via the GitHub API.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: slow down GitHub Actions dependency updates to biweekly

Dependabot has no native biweekly interval. Combining weekly checks with
a 14-day cooldown achieves the same effect: Dependabot scans every Monday
but won't open a PR for a new action version until 14 days after release,
giving the ecosystem time to stabilize before we adopt it.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: group all Dependabot updates into single PRs per ecosystem

Without groups, Dependabot opens one PR per dependency. With `patterns: "*"`,
all Go module bumps land in one PR and all GitHub Actions pin updates in
another, reducing review noise.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: restore credential persistence for helm-charts push

`persist-credentials: false` was too broad — the helm-charts checkout
uses HELM_PUSH_TOKEN specifically so the subsequent `git push` can
authenticate. Only the main repo checkout should have credentials disabled.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: use --password-stdin for oras login

Passing the token via `-p` exposes it in process listings and debug
logs. Piping via stdin is the standard secure pattern for CLI auth.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

* ci: pin actions to versioned release SHAs

jmgilman/actions-generate-checksum: v1 branch HEAD -> v1.0.1 release
mikefarah/yq: arbitrary master HEAD -> v4.52.5 release

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>

---------

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
2026-04-10 15:35:22 -07:00

272 lines
8.0 KiB
YAML

name: "GC stress test"
on:
push:
branches:
- main
pull_request:
branches: [main]
release:
types:
- published
permissions: read-all
jobs:
gc-referrers-stress-local:
name: GC(with referrers) on filesystem with short interval
runs-on: oracle-vm-8cpu-32gb-x86-64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
cache: false
check-latest: true
go-version: 1.25.x
- name: Run zb
id: bench
run: |
make binary
make bench
./bin/zot-linux-amd64 serve test/gc-stress/config-gc-referrers-bench-local.json &
sleep 10
bin/zb-linux-amd64 -c 10 -n 100 -o ci-cd http://localhost:8080
killall -r zot-*
# clean zot storage
sudo rm -rf /tmp/zot
continue-on-error: true
- name: Upload zot logs
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: gc-referrers-bench-local
path: /tmp/gc-referrers-bench-local.log
if-no-files-found: error
- name: Check on failures
if: steps.bench.outcome != 'success'
run: |
cat /tmp/gc-referrers-bench-local.log
exit 1
gc-stress-local:
name: GC(without referrers) on filesystem with short interval
runs-on: oracle-vm-8cpu-32gb-x86-64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
cache: false
check-latest: true
go-version: 1.25.x
- name: Run zb
id: bench
run: |
make binary
make bench
./bin/zot-linux-amd64 serve test/gc-stress/config-gc-bench-local.json &
sleep 10
bin/zb-linux-amd64 -c 10 -n 100 -o ci-cd http://localhost:8080
killall -r zot-*
# clean zot storage
sudo rm -rf /tmp/zot
continue-on-error: true
- name: Upload zot logs
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: gc-bench-local
path: /tmp/gc-bench-local.log
if-no-files-found: error
- name: Check on failures
if: steps.bench.outcome != 'success'
run: |
cat /tmp/gc-bench-local.log
exit 1
gc-referrers-stress-s3:
name: GC(with referrers) on S3(minio) with short interval
runs-on: oracle-vm-8cpu-32gb-x86-64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
cache: false
check-latest: true
go-version: 1.25.x
- uses: ./.github/actions/setup-localstack
- name: Setup minio service
run: |
docker run -d -p 9000:9000 --name minio \
-e "MINIO_ACCESS_KEY=minioadmin" \
-e "MINIO_SECRET_KEY=minioadmin" \
-v /tmp/data:/data \
-v /tmp/config:/root/.minio \
--health-cmd "curl http://localhost:9000/minio/health/live" \
minio/minio:RELEASE.2024-07-16T23-46-41Z server /data
- name: Install py minio
run: pip3 install minio==7.2.18
- name: Wait for minio to come up
run: |
sleep 10
curl --connect-timeout 5 \
--max-time 120 \
--retry 12 \
--retry-max-time 120 \
'http://localhost:9000/minio/health/live'
- name: Create minio bucket
run: |
python3 - <<'EOF'
from minio import Minio
try:
minio = Minio(
'localhost:9000',
access_key='minioadmin',
secret_key='minioadmin',
secure=False
)
except Exception as ex:
raise
minio.make_bucket('zot-storage')
print(f'{minio.list_buckets()}')
EOF
- name: Run zb
id: bench
run: |
make binary
make bench
./bin/zot-linux-amd64 serve test/gc-stress/config-gc-referrers-bench-s3-minio.json &
sleep 10
bin/zb-linux-amd64 -c 10 -n 100 -o ci-cd http://localhost:8080
killall -r zot-*
# clean zot storage
sudo rm -rf /tmp/zot
env:
AWS_ACCESS_KEY_ID: fake
AWS_SECRET_ACCESS_KEY: fake
continue-on-error: true
- name: Upload zot logs
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: gc-referrers-bench-s3
path: /tmp/gc-referrers-bench-s3.log
if-no-files-found: error
- name: Check on failures
if: steps.bench.outcome != 'success'
run: |
cat /tmp/gc-referrers-bench-s3.log
exit 1
- uses: ./.github/actions/teardown-localstack
gc-stress-s3:
name: GC(without referrers) on S3(minio) with short interval
runs-on: oracle-vm-8cpu-32gb-x86-64
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
cache: false
check-latest: true
go-version: 1.25.x
- uses: ./.github/actions/setup-localstack
- name: Setup minio service
run: |
docker run -d -p 9000:9000 --name minio \
-e "MINIO_ACCESS_KEY=minioadmin" \
-e "MINIO_SECRET_KEY=minioadmin" \
-v /tmp/data:/data \
-v /tmp/config:/root/.minio \
--health-cmd "curl http://localhost:9000/minio/health/live" \
minio/minio:RELEASE.2024-07-16T23-46-41Z server /data
- name: Install py minio
run: pip3 install minio==7.2.18
- name: Wait for minio to come up
run: |
sleep 10
curl --connect-timeout 5 \
--max-time 120 \
--retry 12 \
--retry-max-time 120 \
'http://localhost:9000/minio/health/live'
- name: Create minio bucket
run: |
python3 - <<'EOF'
from minio import Minio
try:
minio = Minio(
'localhost:9000',
access_key='minioadmin',
secret_key='minioadmin',
secure=False
)
except Exception as ex:
raise
minio.make_bucket('zot-storage')
print(f'{minio.list_buckets()}')
EOF
- name: Run zb
id: bench
run: |
make binary
make bench
./bin/zot-linux-amd64 serve test/gc-stress/config-gc-bench-s3-minio.json &
sleep 10
bin/zb-linux-amd64 -c 10 -n 100 -o ci-cd http://localhost:8080
killall -r zot-*
# clean zot storage
sudo rm -rf /tmp/zot
env:
AWS_ACCESS_KEY_ID: fake
AWS_SECRET_ACCESS_KEY: fake
continue-on-error: true
- name: Upload zot logs
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: gc-bench-s3
path: /tmp/gc-bench-s3.log
if-no-files-found: error
- name: Check on failures
if: steps.bench.outcome != 'success'
run: |
cat /tmp/gc-bench-s3.log
exit 1
- uses: ./.github/actions/teardown-localstack