1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
stages:
- test
- security
- lint
- fuzz
- publish
# --- GLOBAL CONFIGURATION ---
# Cache Rust artifacts to speed up builds
cache:
paths:
- .cargo/
- target/
- fuzz/target/
# Include GitLab's official security templates here (Top Level)
include:
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml
# --- JOBS ---
# 1. Standard Unit Tests
test:unit:
stage: test
image: rust:latest
script:
- cargo test --lib --verbose
# 2. Rust-Specific Dependency Scanning
audit:dependencies:
stage: security
image: rust:latest
before_script:
- cargo install cargo-audit
script:
- cargo audit
allow_failure: false
# 3. Rust-Specific Linting (Clippy)
clippy:lint:
stage: lint
image: rust:latest
before_script:
- rustup component add clippy
script:
- cargo clippy -- -D warnings
allow_failure: false
# 4. Fuzz Testing
fuzz:smoke-test:
stage: fuzz
image: rustlang/rust:nightly
variables:
FUZZ_TIME: "60"
before_script:
- cargo install cargo-fuzz
script:
# Initialize fuzz folder if not exists (for CI robustness)
- cargo fuzz init || true
- cargo fuzz run fuzz_target_1 -- -max_total_time=$FUZZ_TIME
# --- OVERRIDES FOR INCLUDED TEMPLATES ---
# The SAST template defines a job named 'sast'.
# We reference it here ONLY to override the stage to 'security'
# (it defaults to 'test' in the template).
sast:
stage: security
variables:
SAST_EXCLUDED_PATHS: "target/, .cargo/"
# The Secret Detection template defines 'secret_detection'.
# We override it to ensure it runs in the 'security' stage.
secret_detection:
stage: security
# --- PUBLISH JOBS ---
# Job 1: Publish to GitLab Package Registry
publish:gitlab:
stage: publish
image: rust:latest
rules:
# Only run this job when a tag is created (e.g. "v0.1.0")
- if: $CI_COMMIT_TAG
script:
# 1. Configure Cargo to know about your GitLab Registry
# We write this to .cargo/config.toml dynamically using environment variables
- mkdir -p .cargo
- |
cat <<EOF > .cargo/config.toml
[registries]
gitlab = { index = "sparse+${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/cargo/" }
[registry]
# This mapping ensures cargo uses the CI_JOB_TOKEN to authenticate
global-credential-providers = ["cargo:token-from-stdout"]
[credential-process]
# Helper to inject the token
gitlab = "echo ${CI_JOB_TOKEN}"
EOF
# 2. Publish using the 'gitlab' registry defined above
- cargo publish --registry gitlab
# Job 2: Publish to Crates.io
publish:crates-io:
stage: publish
image: rust:latest
rules:
- if: $CI_COMMIT_TAG
script:
# Cargo publish defaults to crates.io
# We pass the token stored in GitLab Variables
- cargo publish --token $CRATES_IO_TOKEN