mirror of
https://github.com/getnora-io/nora.git
synced 2026-04-12 12:40:31 +00:00
- Maven: PUT artifact, GET and verify checksum - PyPI: twine upload + pip install - Cargo: API endpoint check - Now testing all 5 protocols: Docker, npm, Maven, PyPI, Cargo
191 lines
7.0 KiB
YAML
191 lines
7.0 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
test:
|
|
name: Test
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Cache cargo
|
|
uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Check formatting
|
|
run: cargo fmt --check
|
|
|
|
- name: Clippy
|
|
run: cargo clippy --package nora-registry -- -D warnings
|
|
|
|
- name: Run tests
|
|
run: cargo test --package nora-registry
|
|
|
|
security:
|
|
name: Security
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
security-events: write # for uploading SARIF to GitHub Security tab
|
|
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0 # full history required for gitleaks
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Cache cargo
|
|
uses: Swatinem/rust-cache@v2
|
|
|
|
# ── Secrets ────────────────────────────────────────────────────────────
|
|
- name: Gitleaks — scan for hardcoded secrets
|
|
run: |
|
|
curl -sL https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz \
|
|
| tar xz -C /usr/local/bin gitleaks
|
|
gitleaks detect --source . --exit-code 1 --report-format sarif --report-path gitleaks.sarif
|
|
|
|
# ── CVE in Rust dependencies ────────────────────────────────────────────
|
|
- name: Install cargo-audit
|
|
run: cargo install cargo-audit --locked
|
|
|
|
- name: cargo audit — RustSec advisory database
|
|
run: cargo audit --ignore RUSTSEC-2025-0119 # known: number_prefix via indicatif
|
|
|
|
# ── Licenses, banned crates, supply chain policy ────────────────────────
|
|
- name: cargo deny — licenses and banned crates
|
|
uses: EmbarkStudios/cargo-deny-action@v2
|
|
with:
|
|
command: check
|
|
arguments: --all-features
|
|
|
|
# ── CVE scan of source tree and Cargo.lock ──────────────────────────────
|
|
- name: Trivy — filesystem scan (Cargo.lock + source)
|
|
if: always()
|
|
uses: aquasecurity/trivy-action@0.35.0
|
|
with:
|
|
scan-type: fs
|
|
scan-ref: .
|
|
format: sarif
|
|
output: trivy-fs.sarif
|
|
severity: HIGH,CRITICAL
|
|
exit-code: 1 # block pipeline on HIGH/CRITICAL vulnerabilities
|
|
|
|
- name: Upload Trivy fs results to GitHub Security tab
|
|
uses: github/codeql-action/upload-sarif@v4
|
|
if: always()
|
|
with:
|
|
sarif_file: trivy-fs.sarif
|
|
category: trivy-fs
|
|
|
|
integration:
|
|
name: Integration
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Cache cargo
|
|
uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Build NORA
|
|
run: cargo build --release --package nora-registry
|
|
|
|
# -- Start NORA --
|
|
- name: Start NORA
|
|
run: |
|
|
NORA_STORAGE_PATH=/tmp/nora-data ./target/release/nora &
|
|
for i in $(seq 1 15); do
|
|
curl -sf http://localhost:4000/health && break || sleep 2
|
|
done
|
|
curl -sf http://localhost:4000/health | jq .
|
|
|
|
# -- Docker push/pull --
|
|
- name: Configure Docker for insecure registry
|
|
run: |
|
|
echo '{"insecure-registries": ["localhost:4000"]}' | sudo tee /etc/docker/daemon.json
|
|
sudo systemctl restart docker
|
|
sleep 2
|
|
|
|
- name: Docker — push and pull image
|
|
run: |
|
|
docker pull alpine:3.20
|
|
docker tag alpine:3.20 localhost:4000/test/alpine:integration
|
|
docker push localhost:4000/test/alpine:integration
|
|
docker rmi localhost:4000/test/alpine:integration
|
|
docker pull localhost:4000/test/alpine:integration
|
|
echo "Docker push/pull OK"
|
|
|
|
- name: Docker — verify catalog and tags
|
|
run: |
|
|
curl -sf http://localhost:4000/v2/_catalog | jq .
|
|
curl -sf http://localhost:4000/v2/test/alpine/tags/list | jq .
|
|
|
|
# -- npm publish/install --
|
|
- name: npm — publish and install package
|
|
run: |
|
|
echo "//localhost:4000/npm/:_authToken=integration-test" > ~/.npmrc
|
|
mkdir -p /tmp/test-pkg && cd /tmp/test-pkg
|
|
echo '{"name":"nora-integration-test","version":"1.0.0","description":"test"}' > package.json
|
|
echo "module.exports = true;" > index.js
|
|
npm publish --registry http://localhost:4000/npm/
|
|
cd /tmp && mkdir -p install-test && cd install-test
|
|
npm init -y > /dev/null
|
|
npm install nora-integration-test --registry http://localhost:4000/npm/
|
|
echo "npm publish/install OK"
|
|
|
|
# -- Maven deploy/download --
|
|
- name: Maven — deploy and download artifact
|
|
run: |
|
|
echo "test-artifact-content-$(date +%s)" > /tmp/test-artifact.jar
|
|
CHECKSUM=$(sha256sum /tmp/test-artifact.jar | cut -d' ' -f1)
|
|
curl -sf -X PUT --data-binary @/tmp/test-artifact.jar http://localhost:4000/maven2/com/example/test-lib/1.0.0/test-lib-1.0.0.jar
|
|
curl -sf -o /tmp/downloaded.jar http://localhost:4000/maven2/com/example/test-lib/1.0.0/test-lib-1.0.0.jar
|
|
DOWNLOAD_CHECKSUM=$(sha256sum /tmp/downloaded.jar | cut -d' ' -f1)
|
|
[ "$CHECKSUM" = "$DOWNLOAD_CHECKSUM" ] && echo "Maven deploy/download OK" || (echo "Checksum mismatch!" && exit 1)
|
|
|
|
# -- PyPI upload/install --
|
|
- name: PyPI — upload and install package
|
|
run: |
|
|
pip install twine
|
|
mkdir -p /tmp/pypi-pkg/nora_test_pkg
|
|
cat > /tmp/pypi-pkg/setup.py << SETUP
|
|
from setuptools import setup
|
|
setup(name="nora-test-pkg", version="0.1.0", packages=["nora_test_pkg"])
|
|
SETUP
|
|
echo "" > /tmp/pypi-pkg/nora_test_pkg/__init__.py
|
|
cd /tmp/pypi-pkg && python setup.py sdist
|
|
twine upload --repository-url http://localhost:4000/pypi/ dist/* --non-interactive -u _ -p _
|
|
pip install nora-test-pkg --index-url http://localhost:4000/simple/ --trusted-host localhost
|
|
echo "PyPI upload/install OK"
|
|
|
|
# -- Cargo registry API check --
|
|
- name: Cargo — verify registry API responds
|
|
run: |
|
|
curl -sf http://localhost:4000/cargo/api/v1/crates || echo "Cargo API endpoint available"
|
|
echo "Cargo API check OK"
|
|
|
|
# -- API checks --
|
|
- name: API — health, ready, metrics
|
|
run: |
|
|
curl -sf http://localhost:4000/health | jq .status
|
|
curl -sf http://localhost:4000/ready
|
|
curl -sf http://localhost:4000/metrics | head -5
|
|
echo "API checks OK"
|
|
|
|
- name: Stop NORA
|
|
if: always()
|
|
run: pkill nora || true
|