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
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,43 @@ Ollama is never installed inside the container (Constitution I). When
the endpoint is empty or unreachable, the container starts normally and
Dewey falls back to keyword search.

### Factory URLs

Eclipse Che supports one-click workspace creation via factory URLs.
Navigate to the URL and Che creates a workspace automatically.

By default, Che uses `devfile.yaml` at the repository root:

```
https://<che-host>/#https://github.com/unbound-force/containerfile
```

To use the dynamic devfile (UDI + postStart), append the devfile path:

```
https://<che-host>/#https://github.com/unbound-force/containerfile?devfilePath=devfile-dynamic.yaml
```

Replace `<che-host>` with your Eclipse Che instance hostname
(e.g., `che.example.com`).

### Red Hat Dev Spaces

Expected to be compatible with Red Hat OpenShift Dev Spaces. Not yet
tested in a Dev Spaces environment.

Known differences from open-source Eclipse Che:

- **Per-user namespaces** — Dev Spaces creates a Kubernetes namespace
per user automatically
- **OpenShift OAuth** — SSO via OpenShift identity provider instead of
standalone Keycloak
- **Image registry** — container images must come from a trusted
registry (quay.io is fine)

For more information, see the
[Red Hat Dev Spaces documentation](https://developers.redhat.com/products/openshift-dev-spaces/overview).

## Security Model

These constraints are non-negotiable:
Expand Down
27 changes: 18 additions & 9 deletions devfile-dynamic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,25 @@ commands:
exec:
component: dev-container
commandLine: |
# Install UF tools via go install + npm
if [ -f /projects/scripts/install-uf-tools.sh ]; then
bash /projects/scripts/install-uf-tools.sh
else
echo "install-uf-tools.sh not found in /projects/scripts/"
echo "Clone the containerfile repo or provide the script."
exit 1
fi
# Downloads install script from containerfile repo — works with any cloned project.
# Uses main branch (not SHA-pinned) so workspaces always get the latest tools.
# Retry up to 3 times for transient CDN failures (rate limiting, 503s).
for attempt in 1 2 3; do
if curl -fsSL --max-time 60 https://raw.githubusercontent.com/unbound-force/containerfile/main/scripts/install-uf-tools.sh | bash; then
break
fi
if [ "$attempt" -eq 3 ]; then
echo "WARNING: UF tools installation failed after 3 attempts." >&2
echo "Check network access to raw.githubusercontent.com" >&2
break
fi
echo "Install attempt $attempt failed, retrying in 5s ..."
sleep 5
done
# Install OpenCode via official installer
curl -fsSL https://opencode.ai/install | bash
if ! curl -fsSL --max-time 60 https://opencode.ai/install | bash; then
echo "WARNING: OpenCode installation failed. Check network access to opencode.ai" >&2
fi
workingDir: /projects

- id: start-server
Expand Down
2 changes: 2 additions & 0 deletions openspec/changes/cde-docs/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: unbound-force
created: 2026-04-13
67 changes: 67 additions & 0 deletions openspec/changes/cde-docs/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
## Context

The dynamic devfile's `install-tools` command references a local script
at `/projects/scripts/install-uf-tools.sh` which fails when the cloned
project isn't the containerfile repo. The README lacks factory URL
documentation and Red Hat Dev Spaces notes.

See proposal.md for full motivation and constitution alignment.

## Goals / Non-Goals

### Goals
- Make `devfile-dynamic.yaml` work with any cloned project
- Document factory URL patterns for one-click workspace creation
- Document Red Hat Dev Spaces compatibility (honestly — tested or not)

### Non-Goals
- Modifying `devfile.yaml` (custom image variant already works)
- Changing the install script itself (`scripts/install-uf-tools.sh`)
- Adding credential injection documentation (tracked in Issue #4)
- Adding devfile schema validation to CI

## Decisions

### D1: Curl from GitHub raw URL instead of local script

**Decision**: Replace the local file reference with:
```bash
curl -fsSL https://raw.githubusercontent.com/unbound-force/containerfile/main/scripts/install-uf-tools.sh | bash
```

**Rationale**: This is the simplest approach — no external tooling needed,
same pattern already used for OpenCode installation (`curl | bash`).
The URL points to the `main` branch so it always gets the latest script.
If the repo is private, the URL won't work — but this repo is public.

**Alternatives rejected**:
- Inline the script in the devfile: bloats the YAML, duplicates logic,
maintenance burden
- Download from a release artifact: adds versioning complexity for a
script that should always be latest

### D2: Factory URL documentation scope

**Decision**: Document the factory URL pattern with examples for both
`devfile.yaml` (default) and `devfile-dynamic.yaml` (explicit path).

**Rationale**: Che uses `devfile.yaml` at repo root by default. To use
`devfile-dynamic.yaml`, the factory URL needs `?devfilePath=devfile-dynamic.yaml`.
Both patterns should be documented.

### D3: Dev Spaces honesty policy

**Decision**: Document Dev Spaces as "expected to be compatible" with
known differences called out, but do not claim "tested" unless actually
verified in a Dev Spaces instance.

**Rationale**: Constitution IV (Executable Truth) requires documentation
to be honest. We haven't tested in Dev Spaces, so we say so.

## Risks / Trade-offs

| Risk | Impact | Mitigation |
|------|--------|------------|
| GitHub raw URL unavailable (rate limiting, outage) | Medium — postStart fails | Devfile error message tells user what to check |
| Script changes on main break existing workspaces | Low — script is stable | Version pinning via commit SHA available if needed |
| Dev Spaces has undocumented incompatibilities | Low | Honest documentation; users can file issues |
88 changes: 88 additions & 0 deletions openspec/changes/cde-docs/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
## Why

The CDE devfiles and documentation have three gaps:

1. **Dynamic devfile postStart fails for non-containerfile repos** —
`devfile-dynamic.yaml` references `/projects/scripts/install-uf-tools.sh`
which only exists if the containerfile repo itself is cloned. If an
engineer clones their own project (e.g., `unbound-force/gaze`), the
postStart fails because the script isn't there.

2. **No factory URL documentation** — Eclipse Che supports one-click
workspace creation via factory URLs
(`https://che.example.com/#https://github.com/...`), but this isn't
documented. Engineers don't know they can create a workspace directly
from a GitHub URL.

3. **No Red Hat Dev Spaces notes** — The devfiles should work with
Red Hat OpenShift Dev Spaces (enterprise Che), but compatibility
is undocumented and known differences aren't called out.

Ref: [Issue #5](https://github.com/unbound-force/containerfile/issues/5)

## What Changes

### devfile-dynamic.yaml

Replace the local script reference with a curl download from the
containerfile repo's main branch on GitHub. This removes the
dependency on the containerfile repo being the cloned project.

### README.md

- Add factory URL documentation with patterns and examples
- Add Red Hat Dev Spaces compatibility notes

## Capabilities

### New Capabilities
- `factory-url`: One-click workspace creation via Che factory URL documented
- `remote-install`: Dynamic devfile downloads install script from GitHub (no local dependency)

### Modified Capabilities
- `install-tools` (devfile-dynamic.yaml): Changes from local file reference to curl-from-GitHub download

### Removed Capabilities
- None

## Impact

- **devfile-dynamic.yaml**: `install-tools` command rewritten to use curl
- **README.md**: New "Factory URLs" and "Red Hat Dev Spaces" sections
- **No Containerfile changes**: The install script itself is unchanged
- **No CI changes**: Devfile modifications don't affect container image builds

## Constitution Alignment

Assessed against the containerfile project constitution (v1.0.0).

### I. Composability First

**Assessment**: PASS

The curl-from-GitHub approach improves composability: the dynamic
devfile no longer requires the containerfile repo to be the cloned
project. Any project can use `devfile-dynamic.yaml` by copying it
into their repo — the install script is fetched at runtime.

### II. Security Through Isolation

**Assessment**: N/A

No security model changes. The curl-from-GitHub pattern has the
same risk profile as the existing OpenCode curl installer (already
mitigated by container isolation per Constitution II).

### III. Reproducible Builds

**Assessment**: N/A

No Containerfile or CI changes.

### IV. Executable Truth

**Assessment**: PASS

README documentation will be updated to match the new devfile
behavior. Factory URL patterns will be verified. Dev Spaces
compatibility will be documented honestly (tested vs untested).
60 changes: 60 additions & 0 deletions openspec/changes/cde-docs/specs/cde-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## ADDED Requirements

### Requirement: Factory URL Documentation

README.md MUST document Eclipse Che factory URL patterns for one-click
workspace creation, including:
- Default pattern (`https://che.example.com/#<repo-url>`)
- Explicit devfile path for the dynamic variant
- At least one concrete example URL

#### Scenario: Engineer creates workspace via factory URL
- **GIVEN** an engineer with access to an Eclipse Che instance
- **WHEN** they navigate to `https://che.example.com/#https://github.com/unbound-force/containerfile`
- **THEN** Che creates a workspace using `devfile.yaml` from the repo root

#### Scenario: Engineer uses dynamic devfile via factory URL
- **GIVEN** an engineer who wants the UDI-based dynamic devfile
- **WHEN** they append `?devfilePath=devfile-dynamic.yaml` to the factory URL
- **THEN** Che creates a workspace using `devfile-dynamic.yaml` instead

### Requirement: Red Hat Dev Spaces Documentation

README.md MUST include a "Red Hat Dev Spaces" section noting:
- Expected compatibility status (tested or untested — be honest)
- Known differences from open-source Eclipse Che
- Link to Dev Spaces documentation

#### Scenario: Engineer looks for Dev Spaces guidance
- **GIVEN** an engineer using Red Hat OpenShift Dev Spaces
- **WHEN** they read the README
- **THEN** they find guidance on compatibility and any known differences

## MODIFIED Requirements

### Requirement: Dynamic Devfile Install Script

The `install-tools` command in `devfile-dynamic.yaml` MUST download
`install-uf-tools.sh` from the containerfile repo's GitHub raw URL
instead of referencing a local file path. The download MUST use
`curl -fsSL` with the `main` branch URL.

Previously: The command referenced `/projects/scripts/install-uf-tools.sh`
which only exists when the containerfile repo is the cloned project.

#### Scenario: Dynamic devfile with a non-containerfile project
- **GIVEN** an engineer who clones `unbound-force/gaze` into a Che workspace
using `devfile-dynamic.yaml`
- **WHEN** the postStart event runs `install-tools`
- **THEN** the script is downloaded from GitHub and tools are installed
successfully

#### Scenario: GitHub raw URL is unavailable
- **GIVEN** a workspace where `raw.githubusercontent.com` is unreachable
- **WHEN** the postStart event runs `install-tools`
- **THEN** the curl command fails with a clear error (exit 1) and the
workspace starts without UF tools installed

## REMOVED Requirements

None.
25 changes: 25 additions & 0 deletions openspec/changes/cde-docs/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## 1. Fix Dynamic Devfile Install Script

- [x] 1.1 Replace local script reference in `devfile-dynamic.yaml` `install-tools` command with `curl -fsSL https://raw.githubusercontent.com/unbound-force/containerfile/main/scripts/install-uf-tools.sh | bash`
- [x] 1.2 Keep the OpenCode curl installer line unchanged (already uses curl)
- [x] 1.3 Add a comment in the devfile explaining the GitHub raw URL approach

## 2. Add Factory URL Documentation

- [x] 2.1 Add "Factory URLs" section to README.md under Model C (CDE) documentation
- [x] 2.2 Include default pattern: `https://<che-host>/#https://github.com/unbound-force/containerfile`
- [x] 2.3 Include dynamic devfile pattern: append `?devfilePath=devfile-dynamic.yaml`
- [x] 2.4 Note that Che uses `devfile.yaml` at repo root by default

## 3. Add Red Hat Dev Spaces Notes

- [x] 3.1 Add "Red Hat Dev Spaces" section to README.md
- [x] 3.2 State compatibility status honestly (expected compatible, not yet tested in Dev Spaces)
- [x] 3.3 Note known differences: per-user namespaces, OpenShift OAuth, image registry requirements
- [x] 3.4 Link to Dev Spaces documentation

## 4. Verification

- [x] 4.1 Validate `devfile-dynamic.yaml` parses as valid YAML
- [x] 4.2 Verify the GitHub raw URL resolves (curl exits 0): `curl -fsSL -o /dev/null https://raw.githubusercontent.com/unbound-force/containerfile/main/scripts/install-uf-tools.sh`
- [x] 4.3 Constitution check: Composability (no local dependency), Executable Truth (README matches devfile, honesty about Dev Spaces)
Loading