Skip to content

Commit 2b74745

Browse files
committed
Enhance README.md with detailed project overview, repository layout, release information, and local command instructions for mb3r-stack integration and distribution repository.
1 parent 2e62a9f commit 2b74745

74 files changed

Lines changed: 3423 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: bering-discover
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
target-path:
7+
type: string
8+
default: "."
9+
output-dir:
10+
type: string
11+
default: ".mb3r/bering"
12+
command:
13+
type: string
14+
default: ""
15+
image-ref:
16+
type: string
17+
default: "TODO-SET-BERING-IMAGE"
18+
artifact-name:
19+
type: string
20+
default: "mb3r-bering-discovery"
21+
upload-artifact:
22+
type: boolean
23+
default: true
24+
outputs:
25+
report-path:
26+
description: Discovery envelope JSON path within the artifact.
27+
value: ${{ jobs.bering-discover.outputs.report-path }}
28+
payload-path:
29+
description: Raw discovery payload JSON path within the artifact.
30+
value: ${{ jobs.bering-discover.outputs.payload-path }}
31+
artifact-name:
32+
description: Uploaded artifact name.
33+
value: ${{ jobs.bering-discover.outputs.artifact-name }}
34+
status:
35+
description: Discovery adapter status.
36+
value: ${{ jobs.bering-discover.outputs.status }}
37+
38+
jobs:
39+
bering-discover:
40+
runs-on: ubuntu-latest
41+
outputs:
42+
report-path: ${{ steps.adapter.outputs.report-path }}
43+
payload-path: ${{ steps.adapter.outputs.payload-path }}
44+
artifact-name: ${{ steps.adapter.outputs.artifact-name }}
45+
status: ${{ steps.adapter.outputs.status }}
46+
steps:
47+
- uses: actions/checkout@v4
48+
49+
- uses: actions/setup-python@v5
50+
with:
51+
python-version: "3.13"
52+
53+
- name: Run discovery adapter
54+
id: adapter
55+
shell: bash
56+
env:
57+
TARGET_PATH: ${{ inputs.target-path }}
58+
OUTPUT_DIR: ${{ inputs.output-dir }}
59+
COMMAND: ${{ inputs.command }}
60+
IMAGE_REF: ${{ inputs.image-ref }}
61+
ARTIFACT_NAME: ${{ inputs.artifact-name }}
62+
run: |
63+
python - <<'PY'
64+
import json
65+
import os
66+
import subprocess
67+
from datetime import datetime, timezone
68+
from pathlib import Path
69+
70+
output_dir = Path(os.environ["OUTPUT_DIR"])
71+
output_dir.mkdir(parents=True, exist_ok=True)
72+
payload_path = output_dir / "bering-payload.json"
73+
report_path = output_dir / "bering-discovery.json"
74+
command = os.environ.get("COMMAND", "").strip()
75+
env = os.environ.copy()
76+
env["MB3R_TARGET_PATH"] = os.environ["TARGET_PATH"]
77+
env["MB3R_PAYLOAD_JSON"] = str(payload_path)
78+
env["MB3R_IMAGE_REF"] = os.environ["IMAGE_REF"]
79+
80+
exit_code = 0
81+
status = "pending"
82+
if command:
83+
exit_code = subprocess.run(command, shell=True, env=env, check=False).returncode
84+
status = "success" if exit_code == 0 else "failed"
85+
86+
payload = None
87+
if payload_path.exists():
88+
payload = json.loads(payload_path.read_text(encoding="utf-8"))
89+
if exit_code == 0:
90+
status = "success"
91+
92+
report = {
93+
"schemaVersion": "v1alpha1",
94+
"kind": "mb3r.bering.discovery",
95+
"adapter": "github-reusable-workflow",
96+
"generatedAt": datetime.now(timezone.utc).replace(microsecond=0).isoformat(),
97+
"targetPath": os.environ["TARGET_PATH"],
98+
"imageRef": os.environ["IMAGE_REF"],
99+
"command": command,
100+
"status": status,
101+
"exitCode": exit_code,
102+
"payloadPath": payload_path.as_posix(),
103+
"artifactName": os.environ["ARTIFACT_NAME"],
104+
"payload": payload,
105+
}
106+
report_path.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
107+
108+
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as handle:
109+
handle.write(f"report-path={report_path.as_posix()}\n")
110+
handle.write(f"payload-path={payload_path.as_posix()}\n")
111+
handle.write(f"artifact-name={os.environ['ARTIFACT_NAME']}\n")
112+
handle.write(f"status={status}\n")
113+
114+
if exit_code != 0:
115+
raise SystemExit(exit_code)
116+
PY
117+
118+
- if: ${{ inputs.upload-artifact }}
119+
uses: actions/upload-artifact@v4
120+
with:
121+
name: ${{ steps.adapter.outputs.artifact-name }}
122+
path: ${{ inputs.output-dir }}

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: ci
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
workflow_dispatch:
9+
10+
jobs:
11+
validate:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.13"
19+
20+
- uses: azure/setup-helm@v4
21+
with:
22+
version: v3.15.4
23+
24+
- name: Install dependencies
25+
run: python -m pip install -r requirements.txt
26+
27+
- name: Validate repository
28+
run: make validate
29+
30+
- name: Package chart
31+
run: make chart-package
32+
33+
- name: Package assets
34+
run: make package-assets
35+
36+
- name: Release dry run
37+
run: make release-dry-run
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: example-consumer
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
bering:
8+
uses: ./.github/workflows/bering-discover.yml
9+
with:
10+
command: |
11+
python - <<'PY'
12+
import json
13+
import os
14+
from pathlib import Path
15+
Path(os.environ["MB3R_PAYLOAD_JSON"]).write_text(
16+
json.dumps({"summary": "example discovery", "findings": 0}),
17+
encoding="utf-8",
18+
)
19+
PY
20+
21+
sheaft:
22+
needs: bering
23+
uses: ./.github/workflows/sheaft-gate.yml
24+
with:
25+
discovery-artifact-name: ${{ needs.bering.outputs.artifact-name }}
26+
command: |
27+
python - <<'PY'
28+
import json
29+
import os
30+
from pathlib import Path
31+
Path(os.environ["MB3R_PAYLOAD_JSON"]).write_text(
32+
json.dumps({"decision": "pass", "summary": "example gate"}),
33+
encoding="utf-8",
34+
)
35+
PY
36+
37+
report:
38+
needs:
39+
- bering
40+
- sheaft
41+
uses: ./.github/workflows/mb3r-report.yml
42+
with:
43+
discovery-artifact-name: ${{ needs.bering.outputs.artifact-name }}
44+
gate-artifact-name: ${{ needs.sheaft.outputs.artifact-name }}

.github/workflows/mb3r-report.yml

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: mb3r-report
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
discovery-artifact-name:
7+
type: string
8+
default: "mb3r-bering-discovery"
9+
gate-artifact-name:
10+
type: string
11+
default: "mb3r-sheaft-gate"
12+
discovery-report-path:
13+
type: string
14+
default: ".mb3r/bering/bering-discovery.json"
15+
gate-report-path:
16+
type: string
17+
default: ".mb3r/sheaft/sheaft-gate.json"
18+
output-dir:
19+
type: string
20+
default: ".mb3r/report"
21+
artifact-name:
22+
type: string
23+
default: "mb3r-report"
24+
upload-artifact:
25+
type: boolean
26+
default: true
27+
outputs:
28+
report-json:
29+
description: Combined report JSON path within the artifact.
30+
value: ${{ jobs.mb3r-report.outputs.report-json }}
31+
report-markdown:
32+
description: Combined report markdown path within the artifact.
33+
value: ${{ jobs.mb3r-report.outputs.report-markdown }}
34+
artifact-name:
35+
description: Uploaded artifact name.
36+
value: ${{ jobs.mb3r-report.outputs.artifact-name }}
37+
overall-decision:
38+
description: Overall stack decision from the merged report.
39+
value: ${{ jobs.mb3r-report.outputs.overall-decision }}
40+
41+
jobs:
42+
mb3r-report:
43+
runs-on: ubuntu-latest
44+
outputs:
45+
report-json: ${{ steps.report.outputs.report-json }}
46+
report-markdown: ${{ steps.report.outputs.report-markdown }}
47+
artifact-name: ${{ steps.report.outputs.artifact-name }}
48+
overall-decision: ${{ steps.report.outputs.overall-decision }}
49+
steps:
50+
- if: ${{ inputs.discovery-artifact-name != '' }}
51+
uses: actions/download-artifact@v4
52+
with:
53+
name: ${{ inputs.discovery-artifact-name }}
54+
path: .mb3r/input-discovery
55+
56+
- if: ${{ inputs.gate-artifact-name != '' }}
57+
uses: actions/download-artifact@v4
58+
with:
59+
name: ${{ inputs.gate-artifact-name }}
60+
path: .mb3r/input-gate
61+
62+
- uses: actions/setup-python@v5
63+
with:
64+
python-version: "3.13"
65+
66+
- name: Build combined report
67+
id: report
68+
shell: bash
69+
env:
70+
DISCOVERY_REPORT_PATH: ${{ inputs.discovery-report-path }}
71+
GATE_REPORT_PATH: ${{ inputs.gate-report-path }}
72+
OUTPUT_DIR: ${{ inputs.output-dir }}
73+
ARTIFACT_NAME: ${{ inputs.artifact-name }}
74+
run: |
75+
python - <<'PY'
76+
import json
77+
import os
78+
from datetime import datetime, timezone
79+
from pathlib import Path
80+
81+
output_dir = Path(os.environ["OUTPUT_DIR"])
82+
output_dir.mkdir(parents=True, exist_ok=True)
83+
84+
discovery_report = Path(".mb3r/input-discovery") / Path(os.environ["DISCOVERY_REPORT_PATH"]).name
85+
gate_report = Path(".mb3r/input-gate") / Path(os.environ["GATE_REPORT_PATH"]).name
86+
report_json = output_dir / "mb3r-report.json"
87+
report_md = output_dir / "mb3r-report.md"
88+
89+
discovery = json.loads(discovery_report.read_text(encoding="utf-8"))
90+
gate = json.loads(gate_report.read_text(encoding="utf-8"))
91+
92+
overall_decision = gate.get("decision", "review")
93+
combined = {
94+
"schemaVersion": "v1alpha1",
95+
"kind": "mb3r.stack.report",
96+
"adapter": "github-reusable-workflow",
97+
"generatedAt": datetime.now(timezone.utc).replace(microsecond=0).isoformat(),
98+
"overallDecision": overall_decision,
99+
"discovery": {
100+
"status": discovery.get("status"),
101+
"path": discovery_report.as_posix(),
102+
"artifactName": discovery.get("artifactName"),
103+
},
104+
"gate": {
105+
"decision": gate.get("decision"),
106+
"status": gate.get("status"),
107+
"path": gate_report.as_posix(),
108+
"artifactName": gate.get("artifactName"),
109+
},
110+
}
111+
report_json.write_text(json.dumps(combined, indent=2) + "\n", encoding="utf-8")
112+
113+
markdown = "\n".join(
114+
[
115+
"# MB3R Report",
116+
"",
117+
f"- Generated at: {combined['generatedAt']}",
118+
f"- Discovery status: {combined['discovery']['status']}",
119+
f"- Gate status: {combined['gate']['status']}",
120+
f"- Overall decision: {combined['overallDecision']}",
121+
]
122+
)
123+
report_md.write_text(markdown + "\n", encoding="utf-8")
124+
125+
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as handle:
126+
handle.write(f"report-json={report_json.as_posix()}\n")
127+
handle.write(f"report-markdown={report_md.as_posix()}\n")
128+
handle.write(f"artifact-name={os.environ['ARTIFACT_NAME']}\n")
129+
handle.write(f"overall-decision={overall_decision}\n")
130+
PY
131+
132+
- if: ${{ inputs.upload-artifact }}
133+
uses: actions/upload-artifact@v4
134+
with:
135+
name: ${{ steps.report.outputs.artifact-name }}
136+
path: ${{ inputs.output-dir }}

.github/workflows/release.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
packages: write
12+
13+
jobs:
14+
release:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.13"
22+
23+
- uses: azure/setup-helm@v4
24+
with:
25+
version: v3.15.4
26+
27+
- name: Install dependencies
28+
run: python -m pip install -r requirements.txt
29+
30+
- name: Build release assets
31+
run: make release-dry-run
32+
33+
- name: Log in to GHCR
34+
run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u "${{ github.actor }}" --password-stdin
35+
36+
- name: Push OCI chart
37+
shell: bash
38+
run: |
39+
chart_file=$(find dist/charts -maxdepth 1 -name '*.tgz' | head -n 1)
40+
helm push "$chart_file" "oci://ghcr.io/${{ github.repository_owner }}/charts"
41+
42+
- name: Publish GitHub release
43+
uses: softprops/action-gh-release@v2
44+
with:
45+
files: |
46+
dist/charts/*.tgz
47+
dist/assets/*.tgz
48+
dist/stack-manifest.json
49+
dist/compatibility-matrix.json
50+
dist/SHA256SUMS.txt
51+
dist/sbom.cdx.json

0 commit comments

Comments
 (0)