Skip to content

Commit cfda392

Browse files
authored
Merge branch 'main' into DarkModeUI
2 parents acea5b5 + bbd3657 commit cfda392

File tree

115 files changed

+7572
-2244
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+7572
-2244
lines changed

.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
Dockerfile
2+
Dockerfile.*
3+
Containerfile.*
14
.devcontainer
25
.github
36
docker-compose.yml

.github/tools/cleanup.sh

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env bash
2+
#───────────────────────────────────────────────────────────────────────────────
3+
# Script : cleanup.sh
4+
# Author : Mihai Criveti
5+
# Purpose: Prune old or unused GHCR container versions for IBM's MCP Context Forge
6+
# Copyright 2025
7+
# SPDX-License-Identifier: Apache-2.0
8+
#
9+
# Description:
10+
# This script safely manages container versions in GitHub Container Registry
11+
# (ghcr.io) under the IBM organization, specifically targeting the
12+
# `mcp-context-forge` package. It supports interactive and non-interactive
13+
# deletion modes to help you keep the container registry clean.
14+
#
15+
# Features:
16+
# • Dry-run by default to avoid accidental deletion
17+
# • Tag whitelisting with regular expression matching
18+
# • GitHub CLI integration with scope validation
19+
# • CI/CD-compatible via environment overrides
20+
#
21+
# Requirements:
22+
# • GitHub CLI (gh) v2.x with appropriate scopes
23+
# • jq (command-line JSON processor)
24+
#
25+
# Required Token Scopes:
26+
# delete:packages
27+
#
28+
# Authentication Notes:
29+
# Authenticate with:
30+
# gh auth refresh -h github.com -s read:packages,delete:packages
31+
# Or:
32+
# gh auth logout
33+
# gh auth login --scopes "read:packages,delete:packages,write:packages,repo,read:org,gist"
34+
#
35+
# Verify authentication with:
36+
# gh auth status -t
37+
#
38+
# Environment Variables:
39+
# GITHUB_TOKEN / GH_TOKEN : GitHub token with required scopes
40+
# DRY_RUN : Set to "false" to enable actual deletions (default: true)
41+
#
42+
# Usage:
43+
# ./cleanup.sh # Dry-run with confirmation prompt
44+
# DRY_RUN=false ./cleanup.sh --yes # Actual deletion without prompt (for CI)
45+
#
46+
#───────────────────────────────────────────────────────────────────────────────
47+
48+
set -euo pipefail
49+
50+
##############################################################################
51+
# 1. PICK A TOKEN
52+
##############################################################################
53+
NEEDED_SCOPES="delete:packages"
54+
55+
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
56+
TOKEN="$GITHUB_TOKEN"
57+
elif [[ -n "${GH_TOKEN:-}" ]]; then
58+
TOKEN="$GH_TOKEN"
59+
else
60+
# fall back to whatever gh already has
61+
if ! TOKEN=$(gh auth token 2>/dev/null); then
62+
echo "❌ No token exported and gh not logged in. Fix with:"
63+
echo " gh auth login (or export GITHUB_TOKEN)"
64+
exit 1
65+
fi
66+
fi
67+
export GH_TOKEN="$TOKEN" # gh api uses this
68+
69+
# Fixed scope checking - check for both required scopes individually
70+
if scopes=$(gh auth status --show-token 2>/dev/null | grep -oP 'Token scopes: \K.*' || echo ""); then
71+
missing_scopes=()
72+
73+
# if ! echo "$scopes" | grep -q "read:packages"; then
74+
# missing_scopes+=("read:packages")
75+
# fi
76+
77+
if ! echo "$scopes" | grep -q "delete:packages"; then
78+
missing_scopes+=("delete:packages")
79+
fi
80+
81+
if [[ ${#missing_scopes[@]} -gt 0 ]]; then
82+
echo "⚠️ Your token scopes are [$scopes] – but you're missing: [$(IFS=','; echo "${missing_scopes[*]}")]"
83+
echo " Run: gh auth refresh -h github.com -s $NEEDED_SCOPES"
84+
exit 1
85+
fi
86+
else
87+
echo "⚠️ Could not verify token scopes. Proceeding anyway..."
88+
fi
89+
90+
##############################################################################
91+
# 2. CONFIG
92+
##############################################################################
93+
ORG="ibm"
94+
PKG="mcp-context-forge"
95+
KEEP_TAGS=( "0.1.0" "v0.1.0" "0.1.1" "v0.1.1" "latest" )
96+
PER_PAGE=100
97+
98+
DRY_RUN=${DRY_RUN:-true} # default safe
99+
ASK_CONFIRM=true
100+
[[ ${1:-} == "--yes" ]] && ASK_CONFIRM=false
101+
KEEP_REGEX="^($(IFS='|'; echo "${KEEP_TAGS[*]}"))$"
102+
103+
##############################################################################
104+
# 3. MAIN
105+
##############################################################################
106+
delete_ids=()
107+
108+
echo "📦 Scanning ghcr.io/${ORG}/${PKG}"
109+
110+
# Process versions and collect IDs to delete
111+
while IFS= read -r row; do
112+
id=$(jq -r '.id' <<<"$row")
113+
digest=$(jq -r '.digest' <<<"$row")
114+
tags_csv=$(jq -r '.tags | join(",")' <<<"$row")
115+
keep=$(jq -e --arg re "$KEEP_REGEX" 'any(.tags[]?; test($re))' <<<"$row" 2>/dev/null) || keep=false
116+
117+
if [[ $keep == true ]]; then
118+
printf "✅ KEEP %s [%s]\n" "$digest" "$tags_csv"
119+
else
120+
printf "🗑️ DELETE %s [%s]\n" "$digest" "$tags_csv"
121+
delete_ids+=("$id")
122+
fi
123+
done < <(gh api -H "Accept: application/vnd.github+json" \
124+
"/orgs/${ORG}/packages/container/${PKG}/versions?per_page=${PER_PAGE}" \
125+
--paginate | \
126+
jq -cr --arg re "$KEEP_REGEX" '
127+
.[] |
128+
{
129+
id,
130+
digest: .metadata.container.digest,
131+
tags: (.metadata.container.tags // [])
132+
}
133+
')
134+
135+
##############################################################################
136+
# 4. CONFIRMATION & DELETION
137+
##############################################################################
138+
if [[ ${#delete_ids[@]} -eq 0 ]]; then
139+
echo "✨ Nothing to delete!"
140+
exit 0
141+
fi
142+
143+
if [[ $DRY_RUN == true ]]; then
144+
if [[ $ASK_CONFIRM == true ]]; then
145+
echo
146+
read -rp "Proceed to delete the ${#delete_ids[@]} versions listed above? (y/N) " reply
147+
[[ $reply =~ ^[Yy]$ ]] || { echo "Aborted – nothing deleted."; exit 0; }
148+
fi
149+
echo "🚀 Re-running in destructive mode …"
150+
DRY_RUN=false exec "$0" --yes
151+
else
152+
echo "🗑️ Deleting ${#delete_ids[@]} versions..."
153+
for id in "${delete_ids[@]}"; do
154+
if gh api -X DELETE -H "Accept: application/vnd.github+json" \
155+
"/orgs/${ORG}/packages/container/${PKG}/versions/${id}" >/dev/null 2>&1; then
156+
echo "✅ Deleted version ID: $id"
157+
else
158+
echo "❌ Failed to delete version ID: $id"
159+
fi
160+
done
161+
echo "Done."
162+
fi

.github/workflows/docker-release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ jobs:
7676
# ----------------------------------------------------------------
7777
- name: ✅ Verify commit checks passed
7878
env:
79-
SHA: ${{ steps.meta.outputs.sha }}
80-
REPO: ${{ github.repository }}
79+
SHA: ${{ steps.meta.outputs.sha }}
80+
REPO: ${{ github.repository }}
8181
run: |
8282
set -euo pipefail
8383
STATUS=$(curl -sSL \

.github/workflows/ibm-cloud-code-engine.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
# not the secret value.
3636
# Triggers:
3737
# • Every push to `main`
38+
# • Expects a secret called `mcpgateway-dev` in Code Engine. Ex:
39+
# ibmcloud ce secret create \
40+
# --name mcpgateway-dev \
41+
# --from-env-file .env
3842
# ---------------------------------------------------------------
3943

4044
name: Deploy to IBM Code Engine
@@ -156,6 +160,7 @@ jobs:
156160
--name "$CODE_ENGINE_APP_NAME" \
157161
--image "$REGISTRY_HOSTNAME/$ICR_NAMESPACE/$IMAGE_NAME:$IMAGE_TAG" \
158162
--registry-secret "$CODE_ENGINE_REGISTRY_SECRET" \
163+
--env-from-secret mcpgateway-dev \
159164
--cpu 1 --memory 2G
160165
else
161166
echo "🆕 Creating new application…"
@@ -164,6 +169,7 @@ jobs:
164169
--image "$REGISTRY_HOSTNAME/$ICR_NAMESPACE/$IMAGE_NAME:$IMAGE_TAG" \
165170
--registry-secret "$CODE_ENGINE_REGISTRY_SECRET" \
166171
--port "$PORT" \
172+
--env-from-secret mcpgateway-dev \
167173
--cpu 1 --memory 2G
168174
fi
169175

.github/workflows/lint.yml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# ===============================================================
2+
# 🔍 Lint & Static Analysis – Code Quality Gate
3+
# ===============================================================
4+
#
5+
# - runs each linter in its own matrix job for visibility
6+
# - mirrors the actual CLI commands used locally (no `make`)
7+
# - ensures fast-failure isolation: one failure doesn't hide others
8+
# - each job installs the project in dev-editable mode
9+
# - logs are grouped and plain-text for readability
10+
# ---------------------------------------------------------------
11+
12+
name: Lint & Static Analysis
13+
14+
on:
15+
push:
16+
branches: ["main"]
17+
pull_request:
18+
branches: ["main"]
19+
20+
permissions:
21+
contents: read
22+
23+
jobs:
24+
lint:
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
include:
29+
# -------------------------------------------------------
30+
# 🧼 Syntax & Format Checkers
31+
# -------------------------------------------------------
32+
- id: yamllint
33+
setup: pip install yamllint
34+
cmd: yamllint -c .yamllint .
35+
36+
- id: jsonlint
37+
setup: |
38+
sudo apt-get update -qq
39+
sudo apt-get install -y jq
40+
cmd: |
41+
find . -type f -name '*.json' -not -path './node_modules/*' -print0 |
42+
xargs -0 -I{} jq empty "{}"
43+
44+
- id: tomllint
45+
setup: pip install tomlcheck
46+
cmd: |
47+
find . -type f -name '*.toml' -print0 |
48+
xargs -0 -I{} tomlcheck "{}"
49+
50+
# -------------------------------------------------------
51+
# 🐍 Python Linters & Type Checkers
52+
# -------------------------------------------------------
53+
- id: flake8
54+
setup: pip install flake8
55+
cmd: flake8 mcpgateway
56+
57+
- id: ruff
58+
setup: pip install ruff
59+
cmd: |
60+
ruff check mcpgateway
61+
62+
# - id: pylint
63+
# setup: pip install pylint
64+
# cmd: pylint mcpgateway
65+
66+
# - id: mypy
67+
# setup: pip install mypy
68+
# cmd: mypy mcpgateway
69+
70+
# - id: pycodestyle
71+
# setup: pip install pycodestyle
72+
# cmd: pycodestyle mcpgateway --max-line-length=200
73+
74+
# - id: pydocstyle
75+
# setup: pip install pydocstyle
76+
# cmd: pydocstyle mcpgateway
77+
78+
# - id: pyright
79+
# setup: npm install -g pyright
80+
# cmd: pyright mcpgateway tests
81+
82+
# -------------------------------------------------------
83+
# 🔒 Security & Packaging Checks
84+
# -------------------------------------------------------
85+
# - id: bandit
86+
# setup: pip install bandit
87+
# cmd: bandit -r mcpgateway
88+
89+
# - id: check-manifest
90+
# setup: pip install check-manifest
91+
# cmd: check-manifest
92+
93+
name: ${{ matrix.id }}
94+
runs-on: ubuntu-latest
95+
96+
steps:
97+
# -----------------------------------------------------------
98+
# 0️⃣ Checkout
99+
# -----------------------------------------------------------
100+
- name: ⬇️ Checkout source
101+
uses: actions/checkout@v4
102+
with:
103+
fetch-depth: 1
104+
105+
# -----------------------------------------------------------
106+
# 1️⃣ Python Setup
107+
# -----------------------------------------------------------
108+
- name: 🐍 Set up Python
109+
uses: actions/setup-python@v5
110+
with:
111+
python-version: "3.12"
112+
cache: pip
113+
114+
# -----------------------------------------------------------
115+
# 2️⃣ Install Project + Dev Dependencies
116+
# -----------------------------------------------------------
117+
- name: 📦 Install project (editable mode)
118+
run: |
119+
python -m pip install --upgrade pip
120+
pip install -e .[dev]
121+
122+
# -----------------------------------------------------------
123+
# 3️⃣ Install Tool-Specific Requirements
124+
# -----------------------------------------------------------
125+
- name: 🔧 Install tool - ${{ matrix.id }}
126+
run: ${{ matrix.setup }}
127+
128+
# -----------------------------------------------------------
129+
# 4️⃣ Run Linter / Validator
130+
# -----------------------------------------------------------
131+
- name: 🔍 Run ${{ matrix.id }}
132+
run: ${{ matrix.cmd }}

0 commit comments

Comments
 (0)