diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index 630b045..8ac3c85 100755 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -543,6 +543,40 @@ else info "Pack requests no data volume — skipping mount" fi +# ---- KiroCrew workspace data-volume mapping ---- +step "KiroCrew Workspace Mount" +if [[ "${PACK_NAME}" == "kirocrew" && "${DATA_VOL_GB}" -gt 0 && -d /mnt/ebs-data ]]; then + mkdir -p /mnt/ebs-data/workplace + if ! mountpoint -q /home/ec2-user/workplace; then + if [[ -L /home/ec2-user/workplace ]]; then + rm -f /home/ec2-user/workplace + elif [[ -d /home/ec2-user/workplace ]]; then + if find /home/ec2-user/workplace -mindepth 1 -maxdepth 1 -print -quit | grep -q .; then + cp -a /home/ec2-user/workplace/. /mnt/ebs-data/workplace/ + fi + rm -rf /home/ec2-user/workplace + elif [[ -e /home/ec2-user/workplace ]]; then + fail "KiroCrew workspace path exists but is not a directory" + exit 1 + fi + mkdir -p /home/ec2-user/workplace + mount --bind /mnt/ebs-data/workplace /home/ec2-user/workplace + fi + WORKPLACE_FSTAB_ENTRY="/mnt/ebs-data/workplace /home/ec2-user/workplace none bind,nofail,x-systemd.requires-mounts-for=/mnt/ebs-data 0 0" + sed -i '\|^/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0$|d' /etc/fstab + if ! grep -qF "${WORKPLACE_FSTAB_ENTRY}" /etc/fstab; then + printf '%s\n' "${WORKPLACE_FSTAB_ENTRY}" >> /etc/fstab + fi + chown ec2-user:ec2-user /mnt/ebs-data/workplace /home/ec2-user/workplace + ok "Bind-mounted KiroCrew workplace -> /mnt/ebs-data/workplace" +elif [[ "${PACK_NAME}" == "kirocrew" ]]; then + mkdir -p /home/ec2-user/workplace + chown ec2-user:ec2-user /home/ec2-user/workplace + info "KiroCrew workspace uses the root volume because no data volume is available" +else + info "KiroCrew workspace mount: skipped for ${PACK_NAME}" +fi + # ---- Enable systemd user session for ec2-user (needed by openclaw gateway) ---- loginctl enable-linger ec2-user 2>/dev/null || true # Wait for user runtime dir — linger starts the user manager asynchronously diff --git a/packs/kirocrew/PLAN.md b/packs/kirocrew/PLAN.md index 8072581..1095b9c 100644 --- a/packs/kirocrew/PLAN.md +++ b/packs/kirocrew/PLAN.md @@ -171,7 +171,7 @@ provides: instance_type: t4g.medium root_volume_gb: 40 -data_volume_gb: 0 +data_volume_gb: 80 experimental: true ``` diff --git a/packs/kirocrew/manifest.yaml b/packs/kirocrew/manifest.yaml index 26081f5..61c42df 100644 --- a/packs/kirocrew/manifest.yaml +++ b/packs/kirocrew/manifest.yaml @@ -53,6 +53,6 @@ provides: instance_type: t4g.medium root_volume_gb: 40 -data_volume_gb: 0 +data_volume_gb: 80 experimental: true diff --git a/packs/kirocrew/resources/kirocrew-gateway.service b/packs/kirocrew/resources/kirocrew-gateway.service index 545ef9a..6683090 100644 --- a/packs/kirocrew/resources/kirocrew-gateway.service +++ b/packs/kirocrew/resources/kirocrew-gateway.service @@ -31,6 +31,7 @@ ProtectHome=read-only # that kiro-cli subprocesses (spawned via ACP) may write to. ReadWritePaths=/home/ec2-user/.kiro ReadWritePaths=/home/ec2-user/.local +ReadWritePaths=/home/ec2-user/workplace ReadWritePaths=__HOME__ PrivateTmp=true diff --git a/packs/registry.json b/packs/registry.json index bf09b0c..cfe039c 100644 --- a/packs/registry.json +++ b/packs/registry.json @@ -133,7 +133,7 @@ "deps": [], "instance_type": "t4g.medium", "root_volume_gb": 40, - "data_volume_gb": 0, + "data_volume_gb": 80, "ports": { "gateway": 5476 }, diff --git a/packs/registry.yaml b/packs/registry.yaml index 440ccf5..7d2da6f 100644 --- a/packs/registry.yaml +++ b/packs/registry.yaml @@ -126,7 +126,7 @@ packs: deps: [] instance_type: t4g.medium root_volume_gb: 40 - data_volume_gb: 0 + data_volume_gb: 80 ports: gateway: 5476 brain: false diff --git a/tests/test-kirocrew-ebs.sh b/tests/test-kirocrew-ebs.sh new file mode 100644 index 0000000..ae8aedd --- /dev/null +++ b/tests/test-kirocrew-ebs.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# tests/test-kirocrew-ebs.sh — KiroCrew EBS workspace contract +# Verifies the pack requests a data volume and bootstrap maps the agent workspace +# onto that volume. The test is static because mounting requires a live EC2 host. + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +MANIFEST="${ROOT_DIR}/packs/kirocrew/manifest.yaml" +REGISTRY_YAML="${ROOT_DIR}/packs/registry.yaml" +REGISTRY_JSON="${ROOT_DIR}/packs/registry.json" +BOOTSTRAP="${ROOT_DIR}/deploy/bootstrap.sh" +SERVICE="${ROOT_DIR}/packs/kirocrew/resources/kirocrew-gateway.service" + +PASS=0 +FAIL=0 + +pass() { printf '[PASS] %s\n' "$1"; PASS=$((PASS + 1)); } +fail() { printf '[FAIL] %s\n' "$1"; FAIL=$((FAIL + 1)); } + +if python3 - "$MANIFEST" <<'PY' +import sys +import yaml + +with open(sys.argv[1], encoding="utf-8") as stream: + data = yaml.safe_load(stream) +assert data["data_volume_gb"] == 80 +PY +then + pass "KiroCrew manifest requests an 80 GB data volume" +else + fail "KiroCrew manifest must request an 80 GB data volume" +fi + +if grep -A12 '^ kirocrew:' "$REGISTRY_YAML" | grep -q '^ data_volume_gb: 80$'; then + pass "KiroCrew YAML registry requests an 80 GB data volume" +else + fail "KiroCrew YAML registry must request an 80 GB data volume" +fi + +if python3 - "$REGISTRY_JSON" <<'PY' +import json +import sys + +with open(sys.argv[1], encoding="utf-8") as stream: + data = json.load(stream) +assert data["packs"]["kirocrew"]["data_volume_gb"] == 80 +PY +then + pass "KiroCrew generated registry requests an 80 GB data volume" +else + fail "KiroCrew generated registry must request an 80 GB data volume" +fi + +assert_bootstrap_contains() { + local pattern="$1" + local description="$2" + if grep -Fq "$pattern" "$BOOTSTRAP"; then + pass "$description" + else + fail "$description" + fi +} + +assert_bootstrap_contains \ + 'if [[ "${PACK_NAME}" == "kirocrew" && "${DATA_VOL_GB}" -gt 0 && -d /mnt/ebs-data ]]; then' \ + "bootstrap gates the workspace mapping on KiroCrew and a mounted data volume" +assert_bootstrap_contains \ + 'mount --bind /mnt/ebs-data/workplace /home/ec2-user/workplace' \ + "bootstrap bind-mounts the EBS workplace directory" +assert_bootstrap_contains \ + '/mnt/ebs-data/workplace /home/ec2-user/workplace none bind,nofail,x-systemd.requires-mounts-for=/mnt/ebs-data 0 0' \ + "bootstrap persists a non-fatal workplace bind mount after the data volume" +if grep -Fq 'ReadWritePaths=/home/ec2-user/workplace' "$SERVICE"; then + pass "KiroCrew gateway can write to the EBS-backed workplace" +else + fail "KiroCrew gateway must allow writes to the EBS-backed workplace" +fi + +printf '\nResults: PASS=%d FAIL=%d\n' "$PASS" "$FAIL" +if (( FAIL > 0 )); then + exit 1 +fi