Skip to content

Commit e06ae7a

Browse files
authored
feat: add code ci (#3)
* feat: add code ci Signed-off-by: James Petersen <[email protected]> * chore: fix cargo test Signed-off-by: James Petersen <[email protected]> * chore: fix test and check for existence of certs Signed-off-by: James Petersen <[email protected]> --------- Signed-off-by: James Petersen <[email protected]>
1 parent 972cdbe commit e06ae7a

File tree

8 files changed

+265
-21
lines changed

8 files changed

+265
-21
lines changed

.github/workflows/helm-test.yaml renamed to .github/workflows/ci-chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
- main
77
paths:
88
- charts/**
9-
- .github/workflows/helm-test.yaml
9+
- .github/workflows/ci-chart.yaml
1010

1111
jobs:
1212
lint-test:

.github/workflows/ci-code.yaml

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
name: Lint and Test Code
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
paths:
8+
- src/**
9+
- .github/workflows/ci-code.yaml
10+
11+
jobs:
12+
rustfmt:
13+
name: rustfmt
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: harden runner
17+
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
18+
with:
19+
egress-policy: audit
20+
21+
- name: checkout repository
22+
uses: actions/checkout@6b42224f41ee5dfe5395e27c8b2746f1f9955030 # v4.2.0
23+
with:
24+
submodules: recursive
25+
persist-credentials: false
26+
27+
- name: 'Install stable rust toolchain with rustfmt'
28+
run: |
29+
rustup update --no-self-update stable
30+
rustup default stable
31+
rustup component add rustfmt
32+
33+
- name: 'cargo fmt'
34+
run: cargo fmt --all -- --check
35+
36+
shfmt:
37+
name: shfmt
38+
runs-on: ubuntu-latest
39+
steps:
40+
- name: harden runner
41+
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
42+
with:
43+
egress-policy: audit
44+
45+
- name: checkout repository
46+
uses: actions/checkout@6b42224f41ee5dfe5395e27c8b2746f1f9955030 # v4.2.0
47+
with:
48+
submodules: recursive
49+
persist-credentials: false
50+
51+
- name: shfmt
52+
run: |
53+
GOBIN=/usr/local/bin go install mvdan.cc/sh/v3/cmd/shfmt@latest
54+
if ! ./hack/code/shfmt.sh; then
55+
echo ""
56+
echo "Please run \`PROTECT_SHFMT_WRITE=true ./hack/code/shfmt.sh\`"
57+
fi
58+
59+
shellcheck:
60+
name: shellcheck
61+
runs-on: ubuntu-latest
62+
steps:
63+
- name: harden runner
64+
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
65+
with:
66+
egress-policy: audit
67+
68+
- name: checkout repository
69+
uses: actions/checkout@6b42224f41ee5dfe5395e27c8b2746f1f9955030 # v4.2.0
70+
with:
71+
submodules: recursive
72+
persist-credentials: false
73+
74+
- name: shellcheck
75+
run: ./hack/code/shellcheck.sh
76+
77+
full-build:
78+
runs-on: ubuntu-latest
79+
strategy:
80+
fail-fast: false
81+
matrix:
82+
arch:
83+
- x86_64
84+
env:
85+
TARGET_ARCH: "${{ matrix.arch }}"
86+
name: 'Full build linux-${{ matrix.arch }}'
87+
steps:
88+
- name: harden runner
89+
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
90+
with:
91+
egress-policy: audit
92+
93+
- name: checkout repository
94+
uses: actions/checkout@6b42224f41ee5dfe5395e27c8b2746f1f9955030 # v4.2.0
95+
with:
96+
submodules: recursive
97+
persist-credentials: false
98+
99+
- name: 'Install stable rust toolchain'
100+
run: |
101+
rustup update --no-self-update stable
102+
rustup default stable
103+
104+
- name: cargo build
105+
run: cargo build
106+
107+
full-test:
108+
runs-on: ubuntu-latest
109+
strategy:
110+
fail-fast: false
111+
matrix:
112+
arch:
113+
- x86_64
114+
env:
115+
TARGET_ARCH: "${{ matrix.arch }}"
116+
name: 'Full test linux-${{ matrix.arch }}'
117+
steps:
118+
- name: harden runner
119+
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
120+
with:
121+
egress-policy: audit
122+
123+
- name: checkout repository
124+
uses: actions/checkout@6b42224f41ee5dfe5395e27c8b2746f1f9955030 # v4.2.0
125+
with:
126+
submodules: recursive
127+
persist-credentials: false
128+
129+
- name: 'Install stable rust toolchain'
130+
run: |
131+
rustup update --no-self-update stable
132+
rustup default stable
133+
134+
- name: 'cargo test'
135+
run: cargo test
136+
137+
full-clippy:
138+
runs-on: ubuntu-latest
139+
strategy:
140+
matrix:
141+
arch:
142+
- x86_64
143+
env:
144+
TARGET_ARCH: "${{ matrix.arch }}"
145+
name: 'Full clippy linux-${{ matrix.arch }}'
146+
steps:
147+
- name: harden runner
148+
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
149+
with:
150+
egress-policy: audit
151+
152+
- name: checkout repository
153+
uses: actions/checkout@6b42224f41ee5dfe5395e27c8b2746f1f9955030 # v4.2.0
154+
with:
155+
submodules: recursive
156+
persist-credentials: false
157+
158+
- name: 'Install stable rust toolchain with clippy'
159+
run: |
160+
rustup update --no-self-update stable
161+
rustup default stable
162+
rustup component add clippy
163+
164+
- name: 'cargo clippy'
165+
run: cargo clippy

.github/workflows/release-artifacts.yaml renamed to .github/workflows/release.yaml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@ name: Release Artifacts
22
run-name: 'Release run by ${{ github.actor }}'
33

44
on:
5-
# Release unstable from HEAD on every merge
6-
push:
7-
branches:
8-
- main
9-
10-
# Run manually to release unstable from HEAD
11-
workflow_dispatch:
12-
135
# Official stable versioned release
146
release:
157
types:
@@ -124,22 +116,27 @@ jobs:
124116
- name: Resolve parameters
125117
id: resolve_parameters
126118
run: |
127-
resolved_ref="${{ github.ref }}"
128-
echo "INFO: Resolving short SHA for $resolved_ref"
129-
echo "short_sha=$(git rev-parse --short $resolved_ref)" >> $GITHUB_OUTPUT
119+
echo "INFO: Resolving short SHA for ${GITHUB_REF}"
120+
echo "short_sha=$(git rev-parse --short ${GITHUB_REF})" >> $GITHUB_OUTPUT
130121
echo "INFO: Normalizing repository name (lowercase)"
131-
echo "repository_owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
122+
echo "repository_owner=$(echo ${GITHUB_REPOSITORY_OWNER} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
123+
env:
124+
GITHUB_REF: '${{ github.ref }}'
125+
GITHUB_REPOSITORY_OWNER: '${{ github.repository_owner }}'
132126

133127
- name: Set up Helm
134128
uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2
135129

136130
- name: Publish new helm chart for protect-webhook
137131
run: |
138-
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
132+
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io --username ${GITHUB_ACTOR} --password-stdin
139133
PROTECT_WEBHOOK_CHART_VERSION_TAG=$(cat charts/protect-webhook/Chart.yaml | grep version: | cut -d " " -f 2)
140134
echo "PROTECT_WEBHOOK_CHART_VERSION_TAG=${PROTECT_WEBHOOK_CHART_VERSION_TAG}" >> $GITHUB_ENV
141135
helm package charts/protect-webhook/ --version="${PROTECT_WEBHOOK_CHART_VERSION_TAG}"
142136
helm push protect-webhook-"${PROTECT_WEBHOOK_CHART_VERSION_TAG}".tgz oci://ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/charts
137+
env:
138+
GITHUB_ACTOR: '${{ github.actor }}'
139+
GITHUB_REPOSITORY_OWNER: '${{ github.repository_owner }}'
143140

144141
- name: Job summary
145142
run: |

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Edera Protect Runtime Class Injector
22

3-
This repo contains a mutating webhook to inject the `edera` runtime class into a kubernetes manifest.
3+
protect-webhook is a mutating webhook to inject the `edera` runtime class into a kubernetes manifest.
44

5-
### Why would I want this?
5+
### Uses
66

77
Edera Protect provides strong isolation for kubernetes workloads (see [edera.dev](https://edera.dev)
88
for more details). It does so by utilizing a runtime class name to specify whichworkloads should be
@@ -11,7 +11,7 @@ use of this webhook to inject it into the manifest upon creation. You also might
1111
every manifest you've ever created. Instead you can just use this mutating webhook to set a runtime
1212
class name for manifests without ever touching their yaml.
1313

14-
### Quickstart
14+
### Installation
1515

1616
You can get started quickly by setting up self-signed certificates and then deploying the helm chart.
1717
It deploys a mutating webhook which needs certs to communicate with the API Server. You can find an
@@ -24,3 +24,7 @@ helm upgrade --install mutate oci://ghcr.io/edera-dev/charts/protect-webhook \
2424
--create-namespace \
2525
--values ./examples/self-signed-certs/values.yaml
2626
```
27+
28+
### Troubleshooting
29+
30+
If you're running into issues, please file an issue!

hack/code/shellcheck.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
set -e
3+
4+
REAL_SCRIPT="$(realpath "${0}")"
5+
cd "$(dirname "${REAL_SCRIPT}")/../.."
6+
7+
find hack -type f -name '*.sh' -print0 | xargs -0 shellcheck -x

hack/code/shfmt.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/sh
2+
set -e
3+
4+
REAL_SCRIPT="$(realpath "${0}")"
5+
cd "$(dirname "${REAL_SCRIPT}")/../.."
6+
7+
# Pulled from the flags resembling the google style guide here
8+
# https://github.com/mvdan/sh/blob/master/cmd/shfmt/shfmt.1.scd#examples
9+
FLAGS="--indent 2 --case-indent --binary-next-line --list"
10+
11+
if [ -z "${PROTECT_SHFMT_WRITE}" ]; then
12+
echo "Running shfmt in diff mode..."
13+
FLAGS="${FLAGS} --diff"
14+
else
15+
echo "Running shfmt in write mode..."
16+
FLAGS="${FLAGS} --write"
17+
fi
18+
19+
echo "shfmt $FLAGS"
20+
21+
# shellcheck disable=SC2086
22+
find . -not -path '*/.*' -type f -name '*.sh' -print0 | xargs -0 shfmt $FLAGS

src/server/mod.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use anyhow::Result;
1+
use anyhow::{anyhow, Result};
22
use log::info;
3-
use std::env;
3+
use std::{env, fs};
44
use warp::Filter;
55

66
mod healthz;
@@ -13,10 +13,55 @@ fn routes() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection>
1313
.or(healthz::handler())
1414
}
1515

16-
pub async fn start() -> Result<()> {
16+
fn set_certs_dir() -> Result<String> {
1717
let certs_dir = env::var("WEBHOOK_CERTS_DIR").unwrap_or("/certs".to_string());
18+
19+
let meta = match fs::metadata(&certs_dir) {
20+
Err(e) => return Err(anyhow!("Error reading metadata for {}: {}", certs_dir, e)),
21+
Ok(meta) => meta,
22+
};
23+
24+
if !meta.is_dir() {
25+
return Err(anyhow!("{} is not a directory", certs_dir));
26+
}
27+
28+
Ok(certs_dir)
29+
}
30+
31+
fn set_crt_file() -> Result<String> {
1832
let crt_file = env::var("WEBHOOK_CRT_FILE").unwrap_or("tls.crt".to_string());
33+
34+
let meta = match fs::metadata(&crt_file) {
35+
Err(e) => return Err(anyhow!("Error reading metadata for {}: {}", crt_file, e)),
36+
Ok(meta) => meta,
37+
};
38+
39+
if !meta.is_file() {
40+
return Err(anyhow!("{} is not a file", crt_file));
41+
}
42+
43+
Ok(crt_file)
44+
}
45+
46+
fn set_key_file() -> Result<String> {
1947
let key_file = env::var("WEBHOOK_KEY_FILE").unwrap_or("tls.key".to_string());
48+
49+
let meta = match fs::metadata(&key_file) {
50+
Err(e) => return Err(anyhow!("Error reading metadata for {}: {}", key_file, e)),
51+
Ok(meta) => meta,
52+
};
53+
54+
if !meta.is_file() {
55+
return Err(anyhow!("{} is not a file", key_file));
56+
}
57+
58+
Ok(key_file)
59+
}
60+
61+
pub async fn start() -> Result<()> {
62+
let certs_dir = set_certs_dir()?;
63+
let crt_file = set_crt_file()?;
64+
let key_file = set_key_file()?;
2065
info!("configured certs directory to: {}", certs_dir);
2166

2267
// TODO: Make healthz and livez listen on http rather than https if they need to do more

src/server/mutate.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ mod tests {
9494
let admission_review = AdmissionReview {
9595
request: Some(AdmissionRequest {
9696
uid: "test-uid".to_string(),
97+
name: "test-name".to_string(),
98+
namespace: "test-namespace".to_string(),
9799
}),
98100
};
99101

@@ -138,7 +140,9 @@ mod tests {
138140

139141
let admission_review = json!({
140142
"request": {
141-
"uid": "test-uid"
143+
"uid": "test-uid",
144+
"name": "test-name",
145+
"namespace": "test-namespace",
142146
}
143147
});
144148

0 commit comments

Comments
 (0)