Skip to content

Commit 20db694

Browse files
authored
feat: migrate from GitPod to GitHub Codespaces (#1678)
* 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 .gitignore for local development files - Set default empty values for GITPOD_WORKSPACE_URL to suppress warnings Features: - Automatic yq installation for YAML processing - Port forwarding for Jenkins (8080) with public visibility - Environment-aware URL configuration using CODESPACE_NAME - Maintains backward compatibility with GitPod configuration - 60 hours/month free tier (sufficient for all tutorials) - Welcome message displayed on every terminal session The migration maintains dual support for both Codespaces and GitPod during the transition period, allowing users to choose their preferred environment. * fix: add welcome message to .bashrc for persistent display Configure setup script to append welcome message to .bashrc so it displays automatically on every new terminal session in Codespaces. This is more reliable than postStartCommand which doesn't always show output in the terminal. * fix: add automated port visibility setting and troubleshooting docs Add gh CLI command to automatically set port 8080 to public during setup. Create .devcontainer/README.md with manual steps for port visibility. The devcontainer.json visibility setting doesn't reliably work, so we now: 1. Attempt automatic setting via gh CLI in setup.sh 2. Provide clear manual steps in README if automation fails This addresses the persistent issue where ports default to private even with visibility: public in devcontainer.json. * fix: open Jenkins in browser instead of VS Code preview Change onAutoForward from 'openPreview' to 'openBrowser' to avoid preview pane issues with Jenkins security headers. The VS Code preview shows 'Please reopen the preview' due to Jenkins X-Frame-Options headers. Opening in a regular browser tab works fine. Updated README to clarify this behavior. * chore: disable GitPod Dependabot updates (legacy platform) Add note that GitPod is legacy (free tier sunset) and we've migrated to GitHub Codespaces. Disable Dependabot monitoring of GitPod image updates by setting open-pull-requests-limit to 0. Codespaces uses devcontainer.json which cannot be monitored by Dependabot (not a Dockerfile). Manual updates as needed. * refactor: improve code quality and reproducibility - Pin yq version to v4.44.3 with curl fallback - Pin devcontainer features (Docker 27.0, gh CLI 2.62) - Add shell safety flags (set -Eeuo pipefail) - Replace hardcoded paths with git rev-parse - Improve variable quoting throughout scripts - Add validation checks (yq exists, gh authenticated) - Enhance error handling in all scripts Addresses all valid suggestions from AI reviewers (CodeRabbitAI and Gemini). * feat: add UpdateCLI tracking for Codespaces dependencies - Add updatecli manifest for yq, Docker, and GitHub CLI versions - Update dependabot.yml to reference UpdateCLI for Codespaces deps - Clarify port visibility is not blocking access in README - Document that private ports work for Codespace owners UpdateCLI will now automatically create PRs when new versions of devcontainer dependencies are available. * fix: add missing sourceid to UpdateCLI condition The dockerhub-image-exists condition was missing the required sourceid attribute, causing UpdateCLI validation to fail. Tested locally with updatecli diff - manifest now works correctly and detects available updates: - yq: v4.44.3 → v4.48.1 - Docker: 27.0 → 28.5 - GitHub CLI: 2.62 → 2.81.0 The manifest will run successfully once this PR is merged to main. * fix: correct UpdateCLI regex patterns for file matching Fixed three pattern matching issues: 1. yq pattern: Added missing closing brace '}' before final quote 2. Docker pattern: Simplified to match line-by-line with search filter 3. GitHub CLI pattern: Simplified to match line-by-line with search filter Tested locally - all targets now detect updates correctly: - ⚠ [yq-setup-script] v4.44.3 → v4.48.1 - ⚠ [docker-feature-version] 27.0 → 28.5 - ⚠ [github-cli-feature-version] 2.62 → 2.81.0 * fix: use printf instead of echo for ANSI escape sequences Replaced echo with printf for lines containing ANSI color codes to improve portability across different shells. Fixes Codacy warnings: - Line 44: echo → printf for color formatting - Line 45: echo → printf with proper format string - Line 51: echo → printf in loop with format placeholders The echo command's handling of escape sequences is not standardized across shells. printf is the portable solution and is recommended by POSIX for formatted output. * refactor: use printf directly instead of string concatenation Replace string concatenation with direct printf calls for building the profiles list message. This is more maintainable and consistent with other printf statements in the script. Benefits: - Avoids error-prone string building with ANSI escape sequences - More consistent with the rest of the script - Cleaner and easier to maintain - No temporary variables needed Addresses Copilot AI code review suggestion.
1 parent 2f55a59 commit 20db694

File tree

10 files changed

+755
-10
lines changed

10 files changed

+755
-10
lines changed

.devcontainer/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Codespaces Configuration
2+
3+
This directory contains the GitHub Codespaces dev container configuration.
4+
5+
## Port Visibility
6+
7+
Port 8080 may show as **private** in the PORTS panel, but this is usually not an issue - you can still access Jenkins using the forwarded URL.
8+
9+
**Note:** The port visibility label in the UI can be misleading. Even when marked as "private", the Jenkins URL provided in the welcome message will work in your browser. Only change visibility to "public" if you need to share the URL with others.
10+
11+
### Manual Steps (if needed for sharing):
12+
1. Open the **PORTS** panel at the bottom of VS Code (next to TERMINAL)
13+
2. Find port **8080** in the list
14+
3. **Right-click** on port 8080
15+
4. Select **Port Visibility****Public**
16+
17+
### Technical Details
18+
19+
The `devcontainer.json` includes `"visibility": "public"` for port 8080, but GitHub Codespaces may not always apply this setting automatically. The setup script attempts to set visibility using the GitHub CLI, but this is optional since Codespaces authentication allows private port access.
20+
21+
## Files
22+
23+
- **devcontainer.json** - Dev container specification
24+
- **setup.sh** - Initialization script (installs yq, configures URLs, creates welcome message)
25+
- **welcome.txt** - Generated welcome message (not in git, created at runtime)
26+
- **README.md** - This file
27+
28+
## Accessing Jenkins
29+
30+
After starting a tutorial with `docker compose --profile <name> up -d`:
31+
- Jenkins URL: `https://<codespace>-8080.<domain>` (shown in PORTS panel)
32+
- Default credentials: admin/admin
33+
34+
**Important:** Open Jenkins in a regular browser tab, not the VS Code preview pane. The preview may show "Please reopen the preview" due to Jenkins security headers. Click the globe icon 🌐 in the PORTS panel or copy the URL to your browser.
35+
36+
## Troubleshooting
37+
38+
**Port 8080 refuses connection:**
39+
- Verify Jenkins is running: `docker compose ps`
40+
- Check logs: `docker compose logs jenkins_controller`
41+
- Wait 1-2 minutes for Jenkins to fully start
42+
- Port visibility (private/public) should not affect access for the Codespace owner
43+
44+
**Welcome message not showing:**
45+
- Run: `source ~/.bashrc` in your terminal
46+
- Or open a new terminal window
47+
48+
**yq not found:**
49+
- Run: `bash .devcontainer/setup.sh` manually

.devcontainer/devcontainer.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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": "27.0",
8+
"dockerDashComposeVersion": "v2"
9+
},
10+
"ghcr.io/devcontainers/features/github-cli:1": {
11+
"version": "2.62"
12+
}
13+
},
14+
15+
"onCreateCommand": "bash .devcontainer/setup.sh",
16+
"postStartCommand": "cat .devcontainer/welcome.txt 2>/dev/null || echo 'Run: .devcontainer/setup.sh for tutorial instructions'",
17+
18+
"forwardPorts": [8080, 3000, 5000],
19+
20+
"portsAttributes": {
21+
"8080": {
22+
"label": "Jenkins Controller",
23+
"onAutoForward": "openBrowser",
24+
"protocol": "http",
25+
"visibility": "public"
26+
},
27+
"3000": {
28+
"label": "Application Port (Node/Android/Go)",
29+
"onAutoForward": "notify",
30+
"protocol": "http"
31+
},
32+
"5000": {
33+
"label": "Application Port (Multi/.NET)",
34+
"onAutoForward": "notify",
35+
"protocol": "http"
36+
}
37+
},
38+
39+
"customizations": {
40+
"vscode": {
41+
"extensions": [
42+
"ms-azuretools.vscode-docker",
43+
"redhat.vscode-yaml"
44+
],
45+
"settings": {
46+
"terminal.integrated.defaultProfile.linux": "bash"
47+
}
48+
}
49+
},
50+
51+
"remoteUser": "vscode",
52+
53+
"updateContentCommand": "echo 'Container updated successfully'"
54+
}

.devcontainer/setup.sh

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/usr/bin/env 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 -Eeuo pipefail # Exit on error, undefined variables, pipe failures
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+
YQ_VERSION="${YQ_VERSION:-v4.44.3}"
14+
YQ_URL="https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64"
15+
16+
# Try wget first, fall back to curl if unavailable
17+
if command -v wget &> /dev/null; then
18+
sudo wget -qO /usr/local/bin/yq "${YQ_URL}"
19+
elif command -v curl &> /dev/null; then
20+
sudo curl -fsSL -o /usr/local/bin/yq "${YQ_URL}"
21+
else
22+
echo "❌ Error: Neither wget nor curl found. Cannot download yq."
23+
exit 1
24+
fi
25+
26+
sudo chmod a+x /usr/local/bin/yq
27+
yq --version
28+
29+
# Verify Docker is available
30+
echo "🐳 Verifying Docker installation..."
31+
docker --version
32+
docker compose version
33+
34+
# Create secrets directory if it doesn't exist
35+
echo "📁 Creating secrets directory..."
36+
mkdir -p ./secrets
37+
38+
# Run Codespaces URL configuration script
39+
if [ -f "./dockerfiles/codespacesURL.sh" ]; then
40+
echo "🔧 Configuring Jenkins URLs for Codespaces..."
41+
chmod +x ./dockerfiles/codespacesURL.sh
42+
./dockerfiles/codespacesURL.sh
43+
else
44+
echo "⚠️ Warning: codespacesURL.sh not found, skipping URL configuration"
45+
fi
46+
47+
# Create welcome message for future terminal sessions
48+
WELCOME_FILE=".devcontainer/welcome.txt"
49+
cat > "$WELCOME_FILE" << 'WELCOME_EOF'
50+
51+
================================
52+
🚀 Jenkins Quickstart Tutorials
53+
================================
54+
55+
Available tutorial profiles:
56+
• default : Basic Jenkins with SSH agent
57+
• maven : Jenkins + Maven build environment
58+
• python : Jenkins + Python development
59+
• node : Jenkins + Node.js/npm
60+
• multi : Multibranch pipeline example
61+
• android : Android development
62+
• golang : Go development
63+
• cpp : C++ development
64+
• dotnet : .NET development
65+
• wizard : Jenkins setup wizard (learning)
66+
67+
Quick Start:
68+
docker compose --profile <profile-name> up -d
69+
70+
Examples:
71+
docker compose --profile maven up -d
72+
docker compose --profile node up -d
73+
74+
To build locally:
75+
docker compose -f build-docker-compose.yaml --profile <profile-name> up -d
76+
77+
WELCOME_EOF
78+
79+
# Add Jenkins URL based on environment
80+
if [ -n "${CODESPACE_NAME:-}" ] && [ -n "${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN:-}" ]; then
81+
echo "Jenkins will be accessible at:" >> "${WELCOME_FILE}"
82+
echo " https://${CODESPACE_NAME}-8080.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}" >> "${WELCOME_FILE}"
83+
else
84+
echo "Jenkins will be accessible at:" >> "${WELCOME_FILE}"
85+
echo " http://localhost:8080" >> "${WELCOME_FILE}"
86+
fi
87+
88+
echo "" >> "${WELCOME_FILE}"
89+
echo "Default credentials: admin/admin" >> "${WELCOME_FILE}"
90+
echo "================================" >> "${WELCOME_FILE}"
91+
echo "" >> "${WELCOME_FILE}"
92+
93+
# Display the welcome message
94+
cat "${WELCOME_FILE}"
95+
96+
echo "✅ Setup Complete! Welcome message saved to ${WELCOME_FILE}"
97+
echo ""
98+
99+
# Add welcome message to .bashrc so it shows on every new terminal
100+
# Use git rev-parse to find repo root dynamically instead of hardcoding path
101+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
102+
WELCOME_PATH="${REPO_ROOT}/.devcontainer/welcome.txt"
103+
104+
if ! grep -q "Jenkins Quickstart Tutorials Welcome" ~/.bashrc; then
105+
echo "" >> ~/.bashrc
106+
echo "# Jenkins Quickstart Tutorials Welcome" >> ~/.bashrc
107+
echo "if [ -f \"${WELCOME_PATH}\" ]; then" >> ~/.bashrc
108+
echo " cat \"${WELCOME_PATH}\"" >> ~/.bashrc
109+
echo "fi" >> ~/.bashrc
110+
fi
111+
112+
# Set port 8080 visibility to public using gh CLI (if in Codespaces)
113+
if [ -n "${CODESPACE_NAME:-}" ]; then
114+
echo "🔓 Setting port 8080 visibility to public..."
115+
# Check if gh CLI is authenticated before attempting to set port visibility
116+
if gh auth status &>/dev/null; then
117+
gh codespace ports visibility 8080:public -c "${CODESPACE_NAME}" 2>/dev/null || echo "⚠️ Could not set port visibility automatically. Please set port 8080 to public manually in the PORTS panel."
118+
else
119+
echo "⚠️ gh CLI not authenticated. Please set port 8080 to public manually in the PORTS panel."
120+
fi
121+
fi

.github/dependabot.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
33

44
version: 2
5+
# Note: GitPod support is legacy (free tier sunset). Migrated to GitHub Codespaces.
6+
# Codespaces uses devcontainer.json which Dependabot cannot monitor (not a Dockerfile).
7+
# Codespaces dependencies (yq, devcontainer features) are tracked by UpdateCLI.
8+
# See updatecli/updatecli.d/codespaces.yaml for automated updates.
9+
510
# Enable version updates for GitHub Actions workflows
611
updates:
712
- package-ecosystem: "github-actions"
@@ -62,4 +67,13 @@ updates:
6267
directory: "./dockerfiles/dotnet"
6368
schedule:
6469
interval: weekly
65-
open-pull-requests-limit: 10
70+
open-pull-requests-limit: 10
71+
72+
# GitPod (legacy) - disabled, not actively maintained
73+
- package-ecosystem: docker
74+
directory: "./.gitpod"
75+
schedule:
76+
interval: weekly
77+
open-pull-requests-limit: 0
78+
ignore:
79+
- dependency-name: "gitpod/workspace-full"

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ secrets/*
44
03_maven_tutorial/secrets/*
55
.tutorial_running.txt
66

7+
# Local development files
8+
CLAUDE.md
9+
CONTEXT.md
10+
.devcontainer/welcome.txt

0 commit comments

Comments
 (0)