Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "devpod-mcp",
"name": "devcontainer-mcp",
"build": {
"dockerfile": "Dockerfile"
},
Expand All @@ -14,6 +14,12 @@
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"moby": true,
"dockerDashComposeVersion": "v2"
},
"ghcr.io/devcontainers/features/sshd:1": {
"version": "latest"
},
"ghcr.io/devcontainers/features/github-cli:1": {
"version": "latest"
}
},
"postCreateCommand": ". /usr/local/cargo/env && cargo fetch",
Expand Down
96 changes: 96 additions & 0 deletions .devcontainer/initialize.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# initialize.sh — runs on the HOST before the container starts.
# Grabs the GitHub token and writes it to gh.env for container use.
# If multiple accounts are logged in, uses the active one.
# Set DEVCONTAINER_GH_USER=<login> to override.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GH_ENV_FILE="${SCRIPT_DIR}/gh.env"

# --- Verify gh CLI ---
if ! command -v gh &>/dev/null; then
echo "⚠️ gh CLI not found on host. Codespaces backend will not work."
touch "${GH_ENV_FILE}"
exit 0
fi

echo "🔐 Acquiring GitHub token for devcontainer..."

# Get authenticated accounts from keyring (ignore GH_TOKEN env)
ACCOUNTS_JSON=$(GH_TOKEN="" gh auth status --json hosts 2>/dev/null || echo '{}')

# If user specified an account, use it
if [ -n "${DEVCONTAINER_GH_USER:-}" ]; then
ACCOUNT="${DEVCONTAINER_GH_USER}"
echo "Using specified GitHub account: ${ACCOUNT}"
else
# Pick account: prefer active, fall back to first, prompt if interactive
ACCOUNT=$(echo "$ACCOUNTS_JSON" | python3 -c "
import sys, json
data = json.load(sys.stdin)
hosts = data.get('hosts', {}).get('github.com', [])
ok = [h for h in hosts if h.get('state') == 'success']
active = [h for h in ok if h.get('active')]
pick = active[0] if active else (ok[0] if ok else None)
if pick:
print(pick['login'])
" 2>/dev/null || true)

ACCOUNT_COUNT=$(echo "$ACCOUNTS_JSON" | python3 -c "
import sys, json
data = json.load(sys.stdin)
hosts = data.get('hosts', {}).get('github.com', [])
print(len([h for h in hosts if h.get('state') == 'success']))
" 2>/dev/null || echo 0)

if [ "$ACCOUNT_COUNT" -gt 1 ] && [ -t 0 ]; then
# Interactive terminal — let user choose
ALL_ACCOUNTS=$(echo "$ACCOUNTS_JSON" | python3 -c "
import sys, json
data = json.load(sys.stdin)
hosts = data.get('hosts', {}).get('github.com', [])
for h in hosts:
if h.get('state') == 'success':
marker = ' (active)' if h.get('active') else ''
print(h['login'] + marker)
" 2>/dev/null || true)
echo ""
echo "Multiple GitHub accounts detected:"
i=1
while IFS= read -r acct; do
echo " ${i}) ${acct}"
i=$((i + 1))
done <<< "$ALL_ACCOUNTS"
echo ""
read -rp "Which account? [1-${ACCOUNT_COUNT}] (default: ${ACCOUNT}): " CHOICE
if [ -n "$CHOICE" ]; then
PICKED=$(echo "$ACCOUNTS_JSON" | python3 -c "
import sys, json
data = json.load(sys.stdin)
hosts = data.get('hosts', {}).get('github.com', [])
ok = [h['login'] for h in hosts if h.get('state') == 'success']
idx = int(sys.argv[1]) - 1
print(ok[idx] if 0 <= idx < len(ok) else '')
" "$CHOICE" 2>/dev/null || true)
[ -n "$PICKED" ] && ACCOUNT="$PICKED"
fi
fi
fi

if [ -z "$ACCOUNT" ]; then
echo "🔑 No GitHub accounts found. Logging in..."
GH_TOKEN="" gh auth login -h github.com -p https -w
GH_TOKEN=$(GH_TOKEN="" gh auth token -h github.com 2>/dev/null || true)
else
echo "Using GitHub account: ${ACCOUNT}"
GH_TOKEN=$(GH_TOKEN="" gh auth token -h github.com --user "${ACCOUNT}" 2>/dev/null || true)
fi

if [ -n "${GH_TOKEN:-}" ]; then
echo "GH_TOKEN=${GH_TOKEN}" > "${GH_ENV_FILE}"
echo "✅ GitHub token acquired (${ACCOUNT:-unknown})"
else
touch "${GH_ENV_FILE}"
echo "⚠️ Could not acquire GitHub token — codespaces tools won't work"
fi
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ jobs:
push: never
runCmd: |
cargo fmt --all -- --check
cargo check -p devpod-mcp-core -p devpod-mcp
cargo test -p devpod-mcp-core -p devpod-mcp
cargo clippy -p devpod-mcp-core -p devpod-mcp -- -D warnings
cargo check -p devcontainer-mcp-core -p devcontainer-mcp
cargo test -p devcontainer-mcp-core -p devcontainer-mcp
cargo clippy -p devcontainer-mcp-core -p devcontainer-mcp -- -D warnings
20 changes: 10 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@ jobs:
rustup target add aarch64-unknown-linux-gnu x86_64-unknown-linux-gnu

# Build linux-x64 (native)
cargo build --release --target x86_64-unknown-linux-gnu -p devpod-mcp
cargo build --release --target x86_64-unknown-linux-gnu -p devcontainer-mcp

# Build linux-arm64 (cross-compile with correct linker)
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
cargo build --release --target aarch64-unknown-linux-gnu -p devpod-mcp
cargo build --release --target aarch64-unknown-linux-gnu -p devcontainer-mcp

# Copy binaries to output dir
mkdir -p /tmp/release
cp target/x86_64-unknown-linux-gnu/release/devpod-mcp /tmp/release/devpod-mcp-linux-x64
cp target/aarch64-unknown-linux-gnu/release/devpod-mcp /tmp/release/devpod-mcp-linux-arm64
cp target/x86_64-unknown-linux-gnu/release/devcontainer-mcp /tmp/release/devcontainer-mcp-linux-x64
cp target/aarch64-unknown-linux-gnu/release/devcontainer-mcp /tmp/release/devcontainer-mcp-linux-arm64
chmod +x /tmp/release/*

- name: Upload linux-x64
uses: softprops/action-gh-release@v3
with:
files: /tmp/release/devpod-mcp-linux-x64
files: /tmp/release/devcontainer-mcp-linux-x64

- name: Upload linux-arm64
uses: softprops/action-gh-release@v3
with:
files: /tmp/release/devpod-mcp-linux-arm64
files: /tmp/release/devcontainer-mcp-linux-arm64

build-macos:
name: Build ${{ matrix.artifact }}
Expand All @@ -55,9 +55,9 @@ jobs:
matrix:
include:
- target: x86_64-apple-darwin
artifact: devpod-mcp-darwin-x64
artifact: devcontainer-mcp-darwin-x64
- target: aarch64-apple-darwin
artifact: devpod-mcp-darwin-arm64
artifact: devcontainer-mcp-darwin-arm64
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -68,11 +68,11 @@ jobs:
key: ${{ matrix.target }}

- name: Build
run: cargo build --release --target ${{ matrix.target }} -p devpod-mcp
run: cargo build --release --target ${{ matrix.target }} -p devcontainer-mcp

- name: Package binary
run: |
cp target/${{ matrix.target }}/release/devpod-mcp ${{ matrix.artifact }}
cp target/${{ matrix.target }}/release/devcontainer-mcp ${{ matrix.artifact }}
chmod +x ${{ matrix.artifact }}

- name: Upload release asset
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# DevPod / DevContainer internals
.devcontainer/.devpod-internal/
.devcontainer/devcontainer-lock.json
.devcontainer/gh.env

# IDE
.idea/
Expand Down
9 changes: 5 additions & 4 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
"tasks": [
{
"label": "Build",
"type": "cargo",
"command": "build",
"type": "shell",
"command": "cargo",
"args": [
"build",
"--release",
"-p",
"devpod-mcp"
"devcontainer-mcp"
],
"group": {
"kind": "build",
Expand All @@ -22,7 +23,7 @@
"command": "bash",
"args": [
"-c",
"set -e && targets=(x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu x86_64-apple-darwin aarch64-apple-darwin) && for t in \"${targets[@]}\"; do echo \"\\n==> Building $t\" && rustup target add \"$t\" 2>/dev/null && cargo build --release --target \"$t\" -p devpod-mcp && echo \" ✓ target/$t/release/devpod-mcp\"; done"
"set -e && targets=(x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu x86_64-apple-darwin aarch64-apple-darwin) && for t in \"${targets[@]}\"; do echo \"\\n==> Building $t\" && rustup target add \"$t\" 2>/dev/null && cargo build --release --target \"$t\" -p devcontainer-mcp && echo \" ✓ target/$t/release/devcontainer-mcp\"; done"
],
"group": "build",
"problemMatcher": ["$rustc"]
Expand Down
18 changes: 15 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[workspace]
resolver = "2"
members = [
"crates/devpod-mcp-core",
"crates/devpod-mcp",
"crates/devcontainer-mcp-core",
"crates/devcontainer-mcp",
]

[workspace.package]
edition = "2021"
license = "MIT"
repository = "https://github.com/aniongithub/devpod-mcp"
repository = "https://github.com/aniongithub/devcontainer-mcp"

[workspace.dependencies]
tokio = { version = "1", features = ["full"] }
Expand Down
Loading