diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5dc94fa..c86e3d1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,23 +14,18 @@ } }, - // In Codespaces: set these as Codespace secrets (GitHub Settings → Codespaces → Secrets). - // Locally: export them in your shell before opening the devcontainer. - // ${localEnv:VAR} reads from either source. "containerEnv": { "RW_MODE": "dev", "ROBOT_LOG_DIR": "/robot_logs", - "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}", - "CODECOLLECTION_REPO": "${localEnv:CODECOLLECTION_REPO}", - "CODECOLLECTION_BRANCH": "${localEnv:CODECOLLECTION_BRANCH}", - "PR_NUMBER": "${localEnv:PR_NUMBER}" + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" }, - "onCreateCommand": "bash /home/runwhen/.devcontainer/on-create.sh", "postStartCommand": "python -m http.server --bind 0.0.0.0 --directory /robot_logs 3000 &", "features": { - "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "moby": false + }, "ghcr.io/devcontainers/features/sshd:1": { "version": "latest" } diff --git a/README.md b/README.md index be264e0..b347d8d 100644 --- a/README.md +++ b/README.md @@ -33,32 +33,22 @@ ### Option 1: GitHub Codespaces (recommended for PR review) -Configure environment variables as **Codespace secrets**, then create the Codespace. - -**Step 1 — Set Codespace secrets** (once per user, or per-repo): - -Go to **github.com → Settings → Codespaces → Secrets** (or repo **Settings → Secrets and variables → Codespaces**) and add: - -| Secret | Example | Required | -|--------|---------|----------| -| `CODECOLLECTION_REPO` | `runwhen-contrib/rw-cli-codecollection` | yes | -| `CODECOLLECTION_BRANCH` | `main` | no (defaults to `main`) | -| `PR_NUMBER` | `123` | no (checks out the PR branch) | - -Or set them via the **`gh` CLI**: +1. Go to **github.com/runwhen-contrib/codecollection-devtools** → **Code** → **Codespaces** → **New with options** +2. Pick your branch, region, and machine type → **Create codespace** +3. Once the terminal is ready, bootstrap your codecollection: ```bash -gh secret set CODECOLLECTION_REPO --user --body "runwhen-contrib/rw-cli-codecollection" -gh secret set PR_NUMBER --user --body "123" -``` +# defaults to rw-cli-codecollection on main +task setup -**Step 2 — Create the Codespace:** +# specific repo + PR +task setup REPO=runwhen-contrib/rw-cli-codecollection PR=42 -1. Go to **github.com/runwhen-contrib/codecollection-devtools** → **Code** → **Codespaces** → **New with options** -2. Pick your branch, region, and machine type -3. Click **Create codespace** +# different codecollection and branch +task setup REPO=runwhen-contrib/azure-c7n-codecollection BRANCH=feat/foo +``` -The `on-create.sh` bootstrap script reads those secrets as environment variables, clones the repo, installs dependencies, and checks out the PR automatically. +That clones the repo, installs Python deps, and checks out the PR branch if specified. ### Option 2: VS Code devcontainer (local) @@ -69,18 +59,16 @@ git clone https://github.com/runwhen-contrib/codecollection-devtools.git cd codecollection-devtools ``` -Set environment variables before opening the devcontainer: - -```bash -export CODECOLLECTION_REPO="runwhen-contrib/rw-cli-codecollection" -export CODECOLLECTION_BRANCH="main" -# export PR_NUMBER="123" # optional -``` - Then open in VS Code → **Reopen in Container** (or `Cmd+Shift+P` → "Dev Containers: Reopen in Container"). The devcontainer pulls the pre-built image from GHCR — no local Docker build required. +Once inside the container, bootstrap your codecollection: + +```bash +task setup REPO=runwhen-contrib/rw-cli-codecollection +``` + #### Cursor with GitHub Codespaces Use **Cursor** with a **Codespace** via **`gh codespace ssh`** and **Remote - SSH**. See **[Cursor + Codespaces + devcontainer](docs/cursor-remote-devcontainer.md)**. @@ -89,21 +77,31 @@ Use **Cursor** with a **Codespace** via **`gh codespace ssh`** and **Remote - SS ```bash docker run --rm -it \ - -e CODECOLLECTION_REPO="runwhen-contrib/rw-cli-codecollection" \ -v "$HOME/.kube:/home/runwhen/auth/.kube:ro" \ ghcr.io/runwhen-contrib/codecollection-devtools:latest \ - bash -c 'bash /home/runwhen/.devcontainer/on-create.sh && exec bash' + bash -c 'task setup REPO=runwhen-contrib/rw-cli-codecollection && exec bash' ``` --- +## Task parameters + +`task setup` accepts these variables: + +| Variable | Default | Description | +|----------|---------|-------------| +| `REPO` | `runwhen-contrib/rw-cli-codecollection` | GitHub `org/repo` shorthand or full git URL of the codecollection. | +| `BRANCH` | `main` | Branch to check out after cloning. | +| `PR` | *(none)* | If set, checks out the PR branch via `gh pr checkout`. | + +Other tasks: `task verify` (check tools), `task clean` (remove cloned codecollection). + ## Environment variables +These are set in the container automatically: + | Variable | Default | Description | |----------|---------|-------------| -| `CODECOLLECTION_REPO` | `runwhen-contrib/rw-cli-codecollection` | GitHub `org/repo` shorthand or full git URL of the codecollection to work on. | -| `CODECOLLECTION_BRANCH` | `main` | Branch to check out after cloning. | -| `PR_NUMBER` | *(none)* | If set, checks out the PR branch via `gh pr checkout`. Requires `GITHUB_TOKEN`. | | `GITHUB_TOKEN` | *(injected by Codespaces)* | GitHub token for `gh` CLI auth. Codespaces provides this automatically. | | `RW_MODE` | `dev` | Set to `dev` for local development behavior (handled by `rw-core-keywords`). | @@ -177,15 +175,15 @@ Each codecollection's `requirements.txt` is installed at bootstrap time by `on-c codecollection-devtools/ ├── .devcontainer/ │ ├── devcontainer.json # devcontainer config (pulls pre-built image) -│ └── on-create.sh # bootstrap: clone repo, install deps, checkout PR +│ └── on-create.sh # bootstrap script (called by Taskfile) ├── .github/ │ └── workflows/ │ ├── build-push.yaml # CI: multi-arch build → GHCR + GCP Artifact Registry │ └── pypi.yaml # publish rw-devtools to PyPI (deprecated) +├── Taskfile.yml # task setup, task verify, task clean ├── Dockerfile # image definition (built by CI, not locally) ├── ro # Robot Framework test runner wrapper ├── requirements.txt # base Python dependencies -├── dev_facade/ # DEPRECATED — use rw-core-keywords instead └── README.md ``` @@ -212,12 +210,12 @@ All image builds happen in **GitHub Actions** — never locally: ``` devcontainer opens → pulls pre-built image from GHCR - → runs on-create.sh: - 1. clones CODECOLLECTION_REPO into /home/runwhen/codecollection/ - 2. checks out PR_NUMBER branch (if set) + → starts log HTTP server on port 3000 + → user runs: task setup REPO=org/repo PR=123 + 1. clones repo into /home/runwhen/codecollection/ + 2. checks out PR branch (if PR set) 3. pip installs codecollection's requirements.txt 4. verifies tools (ro, robot, kubectl, gh, python) - → starts log HTTP server on port 3000 → ready to develop ``` diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..91d253f --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,100 @@ +version: "3" + +vars: + RUNWHEN_HOME: /home/runwhen + CODECOLLECTION_DIR: "{{.RUNWHEN_HOME}}/codecollection" + DEFAULT_REPO: runwhen-contrib/rw-cli-codecollection + DEFAULT_BRANCH: main + +tasks: + setup: + desc: Bootstrap a codecollection into this environment + summary: | + Clone a codecollection repo, install its deps, and optionally check out a PR. + + Examples: + task setup # defaults (rw-cli-codecollection, main) + task setup REPO=runwhen-contrib/rw-cli-codecollection PR=42 # specific PR + task setup REPO=runwhen-contrib/azure-c7n-codecollection BRANCH=feat/foo + vars: + REPO: '{{.REPO | default .DEFAULT_REPO}}' + BRANCH: '{{.BRANCH | default .DEFAULT_BRANCH}}' + PR: '{{.PR | default ""}}' + REPO_URL: '{{if or (hasPrefix "http" .REPO) (hasPrefix "git@" .REPO)}}{{.REPO}}{{else}}https://github.com/{{.REPO}}.git{{end}}' + cmds: + - echo "=== CodeCollection DevTools Setup ===" + - echo " Repo {{.REPO_URL}}" + - echo " Branch {{.BRANCH}}" + - 'echo " PR {{if .PR}}#{{.PR}}{{else}}none{{end}}"' + - echo "===================================" + - task: clone + vars: { REPO_URL: "{{.REPO_URL}}", BRANCH: "{{.BRANCH}}" } + - task: checkout-pr + vars: { PR: "{{.PR}}" } + - task: install-deps + - task: verify + + clone: + desc: Clone or update the codecollection repo + internal: true + vars: + REPO_URL: '{{.REPO_URL}}' + BRANCH: '{{.BRANCH}}' + cmds: + - | + if [ -d "{{.CODECOLLECTION_DIR}}/.git" ]; then + echo "Codecollection already cloned, fetching latest..." + git -C "{{.CODECOLLECTION_DIR}}" fetch --all --prune + git -C "{{.CODECOLLECTION_DIR}}" checkout "{{.BRANCH}}" + git -C "{{.CODECOLLECTION_DIR}}" pull --ff-only || true + else + rm -rf "{{.CODECOLLECTION_DIR}}" + echo "Cloning {{.REPO_URL}} → {{.CODECOLLECTION_DIR}} ..." + git clone --branch "{{.BRANCH}}" "{{.REPO_URL}}" "{{.CODECOLLECTION_DIR}}" + fi + + checkout-pr: + desc: Check out a PR branch + internal: true + vars: + PR: '{{.PR}}' + status: + - test -z "{{.PR}}" + cmds: + - echo "Checking out PR #{{.PR}}..." + - cd "{{.CODECOLLECTION_DIR}}" && gh pr checkout "{{.PR}}" + - echo "On branch $(git -C {{.CODECOLLECTION_DIR}} branch --show-current)" + + install-deps: + desc: Install codecollection Python dependencies + internal: true + sources: + - "{{.CODECOLLECTION_DIR}}/requirements.txt" + cmds: + - | + if [ -f "{{.CODECOLLECTION_DIR}}/requirements.txt" ]; then + echo "Installing codecollection requirements..." + pip install --user --no-cache-dir -r "{{.CODECOLLECTION_DIR}}/requirements.txt" + fi + - mkdir -p "{{.RUNWHEN_HOME}}/auth" + + verify: + desc: Check that key tools are available + cmds: + - echo "" + - echo "--- Environment ready ---" + - 'printf " %-12s %s\n" "ro:" "$(command -v ro 2>/dev/null && echo ok || echo MISSING)"' + - 'printf " %-12s %s\n" "robot:" "$(command -v robot 2>/dev/null && echo ok || echo MISSING)"' + - 'printf " %-12s %s\n" "kubectl:" "$(command -v kubectl 2>/dev/null && echo ok || echo MISSING)"' + - 'printf " %-12s %s\n" "gh:" "$(command -v gh 2>/dev/null && echo ok || echo MISSING)"' + - 'printf " %-12s %s\n" "python:" "$(python --version 2>&1)"' + - echo "" + - echo "Codecollection at {{.CODECOLLECTION_DIR}}" + - echo "Run 'cd codecollection/codebundles/ && ro' to test a codebundle." + + clean: + desc: Remove the cloned codecollection (start fresh) + prompt: This will delete {{.CODECOLLECTION_DIR}}. Continue? + cmds: + - rm -rf "{{.CODECOLLECTION_DIR}}" + - echo "Cleaned. Run 'task setup REPO=... ' to start again." diff --git a/docs/cursor-remote-devcontainer.md b/docs/cursor-remote-devcontainer.md index 9bb759c..13d5314 100644 --- a/docs/cursor-remote-devcontainer.md +++ b/docs/cursor-remote-devcontainer.md @@ -4,7 +4,7 @@ Use a **GitHub Codespace** for this repo, then attach **Cursor** with **Remote - The devcontainer includes the [`sshd` feature](https://github.com/devcontainers/features/tree/main/src/sshd) so Codespaces SSH works as documented by GitHub. -> **Note:** The Codespaces "New with options" dialog does **not** have fields for environment variables. Set `CODECOLLECTION_REPO`, `PR_NUMBER`, etc. as **Codespace secrets** in **GitHub Settings → Codespaces → Secrets** (or via `gh secret set … --user`) *before* creating the Codespace. See the [README getting-started section](../README.md#getting-started) for details. +After the Codespace starts, run `task setup REPO=org/repo PR=123` to bootstrap a codecollection. See the [README](../README.md#getting-started) for full details. **Further reading**