Skip to content

Commit c5ec7e7

Browse files
gountharclaude
andcommitted
feat: add GitHub Codespaces support for cloud development
Add comprehensive GitHub Codespaces configuration to replace GitPod as the primary cloud development environment (GitPod free tier has sunset). Changes: - Add .devcontainer/devcontainer.json with Docker-in-Docker and GitHub CLI - Add .devcontainer/setup.sh for automated environment setup - Add dockerfiles/codespacesURL.sh for Codespaces URL configuration - Add CODESPACES_MIGRATION_PLAN.md with detailed migration strategy - Update README.md with Codespaces quick start and instructions - Update CLAUDE.md with Codespaces configuration details Features: - Automatic yq installation for YAML processing - Port forwarding for Jenkins (8080) and applications (3000, 5000) - Environment-aware URL configuration using CODESPACE_NAME - Maintains backward compatibility with GitPod configuration - 60 hours/month free tier (sufficient for all tutorials) The migration maintains dual support for both Codespaces and GitPod during the transition period, allowing users to choose their preferred environment. 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 2f55a59 commit c5ec7e7

File tree

6 files changed

+714
-3
lines changed

6 files changed

+714
-3
lines changed

.devcontainer/devcontainer.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"name": "Jenkins Quickstart Tutorials",
3+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
4+
5+
"features": {
6+
"ghcr.io/devcontainers/features/docker-in-docker:2": {
7+
"version": "latest",
8+
"dockerDashComposeVersion": "v2"
9+
},
10+
"ghcr.io/devcontainers/features/github-cli:1": {
11+
"version": "latest"
12+
}
13+
},
14+
15+
"postCreateCommand": "bash .devcontainer/setup.sh",
16+
17+
"forwardPorts": [8080, 3000, 5000],
18+
19+
"portsAttributes": {
20+
"8080": {
21+
"label": "Jenkins Controller",
22+
"onAutoForward": "openPreview",
23+
"protocol": "http"
24+
},
25+
"3000": {
26+
"label": "Application Port (Node/Android/Go)",
27+
"onAutoForward": "notify",
28+
"protocol": "http"
29+
},
30+
"5000": {
31+
"label": "Application Port (Multi/.NET)",
32+
"onAutoForward": "notify",
33+
"protocol": "http"
34+
}
35+
},
36+
37+
"customizations": {
38+
"vscode": {
39+
"extensions": [
40+
"ms-azuretools.vscode-docker",
41+
"redhat.vscode-yaml"
42+
],
43+
"settings": {
44+
"terminal.integrated.defaultProfile.linux": "bash"
45+
}
46+
}
47+
},
48+
49+
"remoteUser": "vscode",
50+
51+
"updateContentCommand": "echo 'Container updated successfully'"
52+
}

.devcontainer/setup.sh

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/bin/bash
2+
# GitHub Codespaces setup script for Jenkins Quickstart Tutorials
3+
# This script configures the Codespace environment and prepares Jenkins URL configuration
4+
5+
set -e # Exit on error
6+
7+
echo "================================"
8+
echo "Setting up Jenkins Tutorials Environment"
9+
echo "================================"
10+
11+
# Install yq (YAML processor) - required for JCasc configuration
12+
echo "📦 Installing yq YAML processor..."
13+
sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
14+
sudo chmod a+x /usr/local/bin/yq
15+
yq --version
16+
17+
# Verify Docker is available
18+
echo "🐳 Verifying Docker installation..."
19+
docker --version
20+
docker compose version
21+
22+
# Create secrets directory if it doesn't exist
23+
echo "📁 Creating secrets directory..."
24+
mkdir -p ./secrets
25+
26+
# Run Codespaces URL configuration script
27+
if [ -f "./dockerfiles/codespacesURL.sh" ]; then
28+
echo "🔧 Configuring Jenkins URLs for Codespaces..."
29+
chmod +x ./dockerfiles/codespacesURL.sh
30+
./dockerfiles/codespacesURL.sh
31+
else
32+
echo "⚠️ Warning: codespacesURL.sh not found, skipping URL configuration"
33+
fi
34+
35+
# Display available Docker Compose profiles
36+
echo ""
37+
echo "================================"
38+
echo "✅ Setup Complete!"
39+
echo "================================"
40+
echo ""
41+
echo "Available tutorial profiles:"
42+
echo " - default : Basic Jenkins with SSH agent"
43+
echo " - maven : Jenkins + Maven build environment"
44+
echo " - python : Jenkins + Python development"
45+
echo " - node : Jenkins + Node.js/npm"
46+
echo " - multi : Multibranch pipeline example"
47+
echo " - android : Android development"
48+
echo " - golang : Go development"
49+
echo " - cpp : C++ development"
50+
echo " - dotnet : .NET development"
51+
echo " - wizard : Jenkins setup wizard (learning)"
52+
echo ""
53+
echo "To start a tutorial environment:"
54+
echo " docker compose --profile <profile-name> up -d"
55+
echo ""
56+
echo "Example:"
57+
echo " docker compose --profile maven up -d"
58+
echo ""
59+
echo "To build images locally instead of using pre-built ones:"
60+
echo " docker compose -f build-docker-compose.yaml --profile <profile-name> up -d"
61+
echo ""
62+
echo "Jenkins will be accessible at:"
63+
if [ -n "$CODESPACE_NAME" ] && [ -n "$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN" ]; then
64+
echo " https://${CODESPACE_NAME}-8080.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}"
65+
else
66+
echo " http://localhost:8080"
67+
fi
68+
echo ""
69+
echo "Default credentials: admin/admin"
70+
echo ""

CLAUDE.md

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Repository Overview
6+
7+
This repository contains Docker-based Jenkins tutorial files for transitioning from `docker` to `docker compose` in Jenkins tutorials and installation guides. It provides pre-configured Jenkins environments for different technology stacks (Maven, Python, Node.js, Android, Go, C++, .NET) to support the Jenkins documentation tutorials.
8+
9+
## Common Development Commands
10+
11+
### Starting Tutorial Environments
12+
Use Docker Compose profiles to run specific tutorial environments:
13+
14+
```bash
15+
# Start specific tutorials
16+
docker compose --profile maven up -d
17+
docker compose --profile python up -d
18+
docker compose --profile node up -d
19+
docker compose --profile multi up -d
20+
docker compose --profile default up -d
21+
22+
# Build images locally instead of using pre-built ones
23+
docker compose -f build-docker-compose.yaml --profile node up -d
24+
```
25+
26+
### Monitoring and Debugging
27+
```bash
28+
# Check container status
29+
docker ps
30+
docker compose ps
31+
32+
# Access Jenkins at http://127.0.0.1:8080
33+
# Default credentials: admin/admin
34+
35+
# Clean up environments
36+
docker compose --profile <tutorial-name> down
37+
docker compose --profile <tutorial-name> down --remove-orphans
38+
docker compose --profile <tutorial-name> down -v # Remove volumes for fresh start
39+
```
40+
41+
### Testing and Validation
42+
The repository includes automated testing via GitHub Actions:
43+
- **Hadolint**: Docker linting for all Dockerfiles (`.github/workflows/hadolint.yml`)
44+
- **Integration Tests**: Full stack testing that creates Jenkins jobs, runs builds, and validates success (`.github/workflows/test-jenkins.yml`)
45+
- Tests matrix runs against maven, python, and node profiles
46+
- Creates Jenkins job from XML config, launches build, waits for completion, validates SUCCESS status
47+
- Uses Jenkins REST API with token authentication (CRUMB + API token pattern)
48+
49+
## Architecture Overview
50+
51+
### Core Services Architecture
52+
The system uses a multi-container architecture with these core components:
53+
54+
1. **sidekick_service**: Generates SSH keys and JCasc tokens for secure communication between Jenkins controller and agents
55+
2. **discovery_and_jcasc_modifier**: Discovers running agents and dynamically updates Jenkins Configuration as Code (JCasc) to register them
56+
3. **jenkins_controller**: Main Jenkins LTS server with pre-configured plugins and JCasc setup
57+
4. **Tutorial-specific agents**: Specialized build agents (maven, python, node, etc.) with toolchains pre-installed
58+
59+
### Service Dependencies
60+
- All services depend on `sidekick_service` completing successfully (SSH key generation)
61+
- Agents depend on their respective controllers being started
62+
- The discovery service automatically configures agents in Jenkins via JCasc reloading
63+
64+
### Startup Sequence
65+
When you run `docker compose --profile <name> up -d`, services start in this order:
66+
1. **sidekick_service** runs first (no dependencies)
67+
- Generates SSH keys (`jenkins_agent_ed`, `jenkins_agent_ed.pub`)
68+
- Creates JCasc reload token (`secrets/jcasc_token`)
69+
- Writes `conductor_ok` marker file and exits
70+
2. **jenkins_controller** starts after sidekick completes
71+
- Loads plugins from `plugins.txt`
72+
- Reads initial JCasc config from `dockerfiles/jenkins.yaml`
73+
- Mounts SSH private key for agent authentication
74+
- Exposes port 8080 for web UI
75+
3. **discovery_and_jcasc_modifier** starts in parallel with controller
76+
- Waits for `jenkins.yaml` to exist in jenkins_home volume
77+
- Updates CASC_RELOAD_TOKEN in jenkins.yaml
78+
- Scans network for agent container using nmap
79+
- Updates agent hostname in jenkins.yaml
80+
- Triggers JCasc reload via REST API
81+
4. **Tutorial-specific agent** starts after sidekick completes
82+
- Mounts SSH authorized_keys (read-only)
83+
- Waits for controller to be started
84+
- Discovered by nmap scan (hostname contains "agent")
85+
- Automatically registered in Jenkins once discovery completes
86+
87+
### Docker Compose Profiles
88+
The repository uses Docker Compose profiles to organize tutorial environments:
89+
- `default`: Basic Jenkins with SSH agent
90+
- `maven`: Jenkins + Maven build environment
91+
- `python`: Jenkins + Python development tools
92+
- `node`: Jenkins + Node.js/npm environment (exposes port 3000)
93+
- `multi`: Multibranch pipeline example
94+
- `android`: Android development environment
95+
- `golang`: Go development environment
96+
- `cpp`: C++ development environment
97+
- `dotnet`: .NET development environment
98+
- `wizard`: Jenkins setup wizard (for learning)
99+
100+
### Configuration Management
101+
- **JCasc**: Jenkins Configuration as Code for reproducible setups (`dockerfiles/jenkins.yaml`)
102+
- Pre-configured admin user (admin/admin)
103+
- SSH agent credentials loaded from dynamically generated keys
104+
- CASC_RELOAD_TOKEN for hot-reloading configuration
105+
- **Environment Variables**: Configured via `.env` file (GHCR_USERNAME, IMAGE_PREFIX, BRANCH_SUFFIX)
106+
- Default: `ghcr.io/jenkins-docs/quickstart-tutorials`
107+
- BRANCH_SUFFIX enables testing feature branches with different image tags
108+
- **Secrets Management**: Uses Docker secrets and mounted volumes for sensitive data
109+
- SSH keys generated at runtime by sidekick service
110+
- JCasc reload token stored in `secrets/jcasc_token`
111+
- **Agent Discovery**: Automatic agent registration through network discovery and JCasc reloading
112+
- `discovery_and_jcasc_modifier` service uses nmap to find agent containers
113+
- Dynamically updates `jenkins.yaml` with discovered agent hostnames
114+
- Triggers JCasc reload via REST API to register agents without restart
115+
116+
### Dockerfiles Structure
117+
Located in `dockerfiles/` directory:
118+
- **Root Dockerfile**: Jenkins controller with plugins and JCasc configuration
119+
- **Agent subdirectories**: Each tutorial type has specialized Dockerfile with required toolchain
120+
- **sidekick/**: SSH key generation and initial setup utilities
121+
- **agent-discovery/**: Network discovery and JCasc modification logic
122+
123+
### Cloud Development Environments
124+
125+
#### GitHub Codespaces (Recommended)
126+
Configured for cloud-based development via `.devcontainer/`:
127+
- **Configuration**: `.devcontainer/devcontainer.json` - Dev container specification
128+
- **Base Image**: `mcr.microsoft.com/devcontainers/base:ubuntu-24.04`
129+
- **Features**: Docker-in-Docker and GitHub CLI installed automatically
130+
- **Setup Script**: `.devcontainer/setup.sh` - Installs yq and configures environment
131+
- **URL Configuration**: `dockerfiles/codespacesURL.sh` - Adapts Jenkins URLs for Codespaces
132+
- **Port Forwarding**: Ports 8080 (Jenkins), 3000, and 5000 automatically forwarded
133+
- **Environment Variables**:
134+
- `CODESPACE_NAME` - Unique codespace identifier
135+
- `GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN` - Port forwarding domain
136+
- URL format: `https://<codespace>-8080.<domain>`
137+
- **Free Tier**: 60 hours/month (sufficient for tutorials)
138+
139+
#### GitPod (Legacy)
140+
Still supported but GitPod free tier has sunset:
141+
- Configuration via `.gitpod.yml` and `.gitpod/Dockerfile`
142+
- Uses `gitpod/workspace-full` base image with GitHub CLI
143+
- Initialization script `dockerfiles/gitpodURL.sh` configures workspace URLs
144+
- GITPOD_WORKSPACE_URL environment variable for URL rewriting
145+
- Used in node, android, multi, golang, cpp, and dotnet tutorial profiles
146+
147+
## Key Scripts and Utilities
148+
149+
### Bootstrap and Configuration Scripts
150+
Located in `dockerfiles/`:
151+
- **`sidekick/keygen.sh`**: Generates ed25519 SSH key pairs and JCasc reload tokens
152+
- Creates `jenkins_agent_ed` (private key) and `jenkins_agent_ed.pub` (public key)
153+
- Generates random JCasc token via `openssl rand -hex 24`
154+
- Creates `conductor_ok` marker file for service health checks
155+
- All other services depend on successful completion of this script
156+
- **`agent-discovery/find-name.sh`**: Dynamic agent registration via network discovery
157+
- Updates JCasc token in `jenkins.yaml` from generated `jcasc_token` file
158+
- Uses `nmap` to scan network for containers with "agent" in hostname
159+
- Dynamically updates agent host in `jenkins.yaml` using `yq`
160+
- Falls back from `jenkins_controller` to `multi_jenkins_controller` if needed
161+
- Triggers JCasc reload via REST API once agent is discovered
162+
- **`update-plugins.sh`**: Updates Jenkins plugin versions in `plugins.txt`
163+
- **`gitpodURL.sh`**: Configures GitPod workspace-specific URLs for tutorials (legacy)
164+
- **`codespacesURL.sh`**: Configures GitHub Codespaces URLs using CODESPACE_NAME and GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN environment variables
165+
166+
### Plugin Management
167+
- `dockerfiles/plugins.txt`: Defines all required Jenkins plugins with versions
168+
- Plugins installed during controller image build
169+
- Use `update-plugins.sh` to refresh plugin versions
170+
171+
## Docker Image Management
172+
173+
### Environment Configuration
174+
Images are sourced from GitHub Container Registry (GHCR):
175+
- **Registry**: `ghcr.io/jenkins-docs/quickstart-tutorials`
176+
- **Branching**: Images tagged with branch suffix for feature development
177+
- **Local Building**: Use `build-docker-compose.yaml` for local image builds
178+
179+
### Tested Versions
180+
- Docker version: 28.0.4
181+
- Docker Compose version: v2.38.2
182+
183+
## Troubleshooting
184+
185+
### Common Issues
186+
- **Agent not connecting**: Check if `discovery_and_jcasc_modifier` successfully found the agent via nmap
187+
- Verify agent container name contains "agent" string
188+
- Check network connectivity: `docker network inspect quickstart-tutorials_jenkins-net`
189+
- Review logs: `docker compose logs discovery_and_jcasc_modifier`
190+
- **"Resource is still in use" warning**: Use `docker compose --profile <name> down --remove-orphans`
191+
- **Jenkins not starting**:
192+
- Ensure `sidekick_service` completed successfully (creates SSH keys)
193+
- Check for `conductor_ok` marker file in agent-ssh-dir volume
194+
- Verify port 8080 is not already in use
195+
- **Stale volumes preventing fresh start**: Use `docker compose --profile <name> down -v` to remove volumes
196+
- **Profile-specific issues**: Ensure you're using `--profile <name>` flag; running without it leaves controller without agents
197+
198+
### Debugging Workflow
199+
1. Check service health: `docker compose ps`
200+
2. View service logs: `docker compose logs <service-name>`
201+
3. Inspect volumes: `docker volume inspect agent-ssh-dir`
202+
4. Verify JCasc config: Check `/var/jenkins_home/jenkins.yaml` in controller container
203+
5. Test Jenkins API: `curl -I http://admin:[email protected]:8080`

0 commit comments

Comments
 (0)