Skip to content

Commit fd1f8f7

Browse files
committed
add periodic E2E test for codeplain installation and render
1 parent 4fe4819 commit fd1f8f7

9 files changed

Lines changed: 469 additions & 74 deletions

File tree

.github/workflows/e2e.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# .github/workflows/e2e.yml
2+
name: E2E
3+
4+
on:
5+
schedule:
6+
- cron: '0 5 * * 1-5' # weekday nights to catch API drift
7+
workflow_dispatch:
8+
9+
jobs:
10+
e2e-linux:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 15
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: '3.12'
19+
20+
- run: pip install pytest
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
25+
- name: Build E2E image (cached)
26+
uses: docker/build-push-action@v5
27+
with:
28+
context: .
29+
file: tests/e2e/Dockerfile
30+
tags: codeplain-e2e:latest
31+
load: true
32+
cache-from: type=gha
33+
cache-to: type=gha,mode=max
34+
35+
- name: Run E2E tests
36+
env:
37+
CODEPLAIN_API_KEY: ${{ secrets.CODEPLAIN_API_KEY }}
38+
run: pytest tests/e2e/ -v --tb=short
39+
40+
- name: Upload generated outputs on failure
41+
if: failure()
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: e2e-outputs-linux
45+
path: /tmp/pytest-of-runner/**/container_work*/**
46+
47+
e2e-windows:
48+
runs-on: windows-latest
49+
timeout-minutes: 15
50+
steps:
51+
- uses: actions/checkout@v4
52+
53+
- uses: actions/setup-python@v5
54+
with:
55+
python-version: '3.12'
56+
57+
- run: pip install pytest
58+
59+
- name: Run E2E tests
60+
env:
61+
CODEPLAIN_API_KEY: ${{ secrets.CODEPLAIN_API_KEY }}
62+
run: pytest tests/e2e/ -v --tb=short

install/bash/install.sh

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ NC='\033[0m' # No Color / Reset
2222
# Export colors for child scripts
2323
export YELLOW GREEN GREEN_LIGHT GREEN_DARK BLUE BLACK WHITE RED GRAY GRAY_LIGHT BOLD NC
2424

25-
clear
25+
NONINTERACTIVE="${CODEPLAIN_INSTALL_NONINTERACTIVE:-0}"
26+
27+
if [ "$NONINTERACTIVE" = "1" ]; then
28+
echo "running in non-interactive mode (CODEPLAIN_INSTALL_NONINTERACTIVE=1)"
29+
else
30+
clear
31+
fi
2632
echo -e "started ${YELLOW}${BOLD}*codeplain CLI${NC} installation..."
2733

2834
# Install uv if not present
@@ -61,31 +67,42 @@ else
6167
echo -e "installing codeplain...${NC}"
6268
echo -e ""
6369
uv tool install codeplain
64-
clear
70+
if [ "$NONINTERACTIVE" != "1" ]; then
71+
clear
72+
fi
6573
echo -e "${GREEN}✓ codeplain installed successfully!${NC}"
6674
fi
6775

6876
# Check if API key already exists
6977
SKIP_API_KEY_SETUP=false
7078
if [ -n "${CODEPLAIN_API_KEY:-}" ]; then
71-
echo -e " you already have an API key configured."
72-
echo ""
73-
echo -e " would you like to log in and get a new one?"
74-
echo ""
75-
read -r -p " [y/N]: " GET_NEW_KEY < /dev/tty
76-
echo ""
77-
78-
if [[ ! "$GET_NEW_KEY" =~ ^[Yy]$ ]]; then
79-
echo -e "${GREEN}${NC} using existing API key."
79+
if [ "$NONINTERACTIVE" = "1" ]; then
80+
echo -e "${GREEN}${NC} using existing CODEPLAIN_API_KEY (non-interactive mode)."
8081
SKIP_API_KEY_SETUP=true
82+
else
83+
echo -e " you already have an API key configured."
84+
echo ""
85+
echo -e " would you like to log in and get a new one?"
86+
echo ""
87+
read -r -p " [y/N]: " GET_NEW_KEY < /dev/tty
88+
echo ""
89+
90+
if [[ ! "$GET_NEW_KEY" =~ ^[Yy]$ ]]; then
91+
echo -e "${GREEN}${NC} using existing API key."
92+
SKIP_API_KEY_SETUP=true
93+
fi
8194
fi
8295
fi
8396

8497
if [ "$SKIP_API_KEY_SETUP" = false ]; then
85-
echo -e "go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key."
86-
echo ""
87-
read -r -p "paste your API key here: " API_KEY < /dev/tty
88-
echo ""
98+
if [ "$NONINTERACTIVE" = "1" ]; then
99+
echo -e "${GRAY}no CODEPLAIN_API_KEY set; skipping key setup (non-interactive mode).${NC}"
100+
else
101+
echo -e "go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key."
102+
echo ""
103+
read -r -p "paste your API key here: " API_KEY < /dev/tty
104+
echo ""
105+
fi
89106
fi
90107

91108
if [ "$SKIP_API_KEY_SETUP" = true ]; then
@@ -130,7 +147,9 @@ else
130147
fi
131148

132149
# ASCII Art Welcome
133-
clear
150+
if [ "$NONINTERACTIVE" != "1" ]; then
151+
clear
152+
fi
134153
echo ""
135154
echo -e "${NC}"
136155
echo -e "${GRAY}────────────────────────────────────────────${NC}"
@@ -153,10 +172,14 @@ echo ""
153172
echo ""
154173
echo -e "${GRAY}────────────────────────────────────────────${NC}"
155174
echo ""
156-
echo -e " would you like to get a quick intro to ***plain specification language?"
157-
echo ""
158-
read -r -p " [Y/n]: " WALKTHROUGH_CHOICE < /dev/tty
159-
echo ""
175+
if [ "$NONINTERACTIVE" = "1" ]; then
176+
WALKTHROUGH_CHOICE="n"
177+
else
178+
echo -e " would you like to get a quick intro to ***plain specification language?"
179+
echo ""
180+
read -r -p " [Y/n]: " WALKTHROUGH_CHOICE < /dev/tty
181+
echo ""
182+
fi
160183

161184
# Determine script directory for local execution
162185
SCRIPT_DIR=""
@@ -193,27 +216,33 @@ if [[ ! "$WALKTHROUGH_CHOICE" =~ ^[Nn]$ ]]; then
193216
fi
194217

195218
# Download examples step
196-
clear
197-
echo ""
198-
echo -e "${GRAY}────────────────────────────────────────────${NC}"
199-
echo -e " ${YELLOW}${BOLD}Example Projects${NC}"
200-
echo -e "${GRAY}────────────────────────────────────────────${NC}"
201-
echo ""
202-
echo -e " we've prepared some example Plain projects for you"
203-
echo -e " to explore and experiment with."
204-
echo ""
205-
echo -e " would you like to download them?"
206-
echo ""
207-
read -r -p " [Y/n]: " DOWNLOAD_EXAMPLES < /dev/tty
208-
echo ""
219+
if [ "$NONINTERACTIVE" = "1" ]; then
220+
DOWNLOAD_EXAMPLES="n"
221+
else
222+
clear
223+
echo ""
224+
echo -e "${GRAY}────────────────────────────────────────────${NC}"
225+
echo -e " ${YELLOW}${BOLD}Example Projects${NC}"
226+
echo -e "${GRAY}────────────────────────────────────────────${NC}"
227+
echo ""
228+
echo -e " we've prepared some example Plain projects for you"
229+
echo -e " to explore and experiment with."
230+
echo ""
231+
echo -e " would you like to download them?"
232+
echo ""
233+
read -r -p " [Y/n]: " DOWNLOAD_EXAMPLES < /dev/tty
234+
echo ""
235+
fi
209236

210237
# Run examples download if user agrees
211238
if [[ ! "${DOWNLOAD_EXAMPLES:-}" =~ ^[Nn]$ ]]; then
212239
run_script "examples.sh"
213240
fi
214241

215242
# Final message
216-
clear
243+
if [ "$NONINTERACTIVE" != "1" ]; then
244+
clear
245+
fi
217246
echo ""
218247
echo -e "${GRAY}────────────────────────────────────────────${NC}"
219248
echo -e " ${YELLOW}${BOLD}You're all set!${NC}"
@@ -230,6 +259,8 @@ echo ""
230259
echo -e " ${GREEN}happy development!${NC} 🚀"
231260
echo ""
232261

233-
# Replace this subshell with a fresh shell that has the new environment
234-
# Reconnect stdin to terminal (needed when running via curl | bash)
235-
exec "$SHELL" < /dev/tty
262+
if [ "$NONINTERACTIVE" != "1" ]; then
263+
# Replace this subshell with a fresh shell that has the new environment
264+
# Reconnect stdin to terminal (needed when running via curl | bash)
265+
exec "$SHELL" < /dev/tty
266+
fi

install/powershell/install.ps1

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
$ErrorActionPreference = 'Stop'
22

3+
# Non-interactive mode for unattended installs (CI, scripted setup). Skips all
4+
# prompts and Clear-Host calls. Same env var name as install.sh.
5+
$nonInteractive = ($env:CODEPLAIN_INSTALL_NONINTERACTIVE -eq "1")
6+
if ($nonInteractive) {
7+
Write-Host "running in non-interactive mode (CODEPLAIN_INSTALL_NONINTERACTIVE=1)"
8+
}
9+
310
# Base URL for additional scripts
411
if (-not $env:CODEPLAIN_SCRIPTS_BASE_URL) {
512
$env:CODEPLAIN_SCRIPTS_BASE_URL = "https://codeplain.ai"
@@ -34,7 +41,7 @@ $env:GRAY_LIGHT = $GRAY_LIGHT
3441
$env:BOLD = $BOLD
3542
$env:NC = $NC
3643

37-
Clear-Host
44+
if (-not $nonInteractive) { Clear-Host }
3845
Write-Host "started ${YELLOW}${BOLD}*codeplain CLI${NC} installation..."
3946

4047
# Install uv if not present
@@ -94,7 +101,7 @@ if ($codeplainLine) {
94101
Write-Host "installing codeplain...${NC}"
95102
Write-Host ""
96103
uv tool install codeplain
97-
Clear-Host
104+
if (-not $nonInteractive) { Clear-Host }
98105
Write-Host "${GREEN}✓ codeplain installed successfully!${NC}"
99106
}
100107

@@ -119,25 +126,34 @@ Write-Host ""
119126
# Check if API key already exists
120127
$skipApiKeySetup = $false
121128
if ($env:CODEPLAIN_API_KEY) {
122-
Write-Host " you already have an API key configured."
123-
Write-Host ""
124-
Write-Host " would you like to log in and get a new one?"
125-
Write-Host ""
126-
$getNewKey = Read-Host " [y/N]"
127-
Write-Host ""
128-
129-
if ($getNewKey -notmatch '^[Yy]$') {
130-
Write-Host "${GREEN}${NC} using existing API key."
129+
if ($nonInteractive) {
130+
Write-Host "${GREEN}${NC} using existing CODEPLAIN_API_KEY (non-interactive mode)."
131131
$skipApiKeySetup = $true
132+
} else {
133+
Write-Host " you already have an API key configured."
134+
Write-Host ""
135+
Write-Host " would you like to log in and get a new one?"
136+
Write-Host ""
137+
$getNewKey = Read-Host " [y/N]"
138+
Write-Host ""
139+
140+
if ($getNewKey -notmatch '^[Yy]$') {
141+
Write-Host "${GREEN}${NC} using existing API key."
142+
$skipApiKeySetup = $true
143+
}
132144
}
133145
}
134146

135147
$apiKey = $null
136148
if (-not $skipApiKeySetup) {
137-
Write-Host "go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key."
138-
Write-Host ""
139-
$apiKey = Read-Host "paste your API key here"
140-
Write-Host ""
149+
if ($nonInteractive) {
150+
Write-Host "${GRAY}no CODEPLAIN_API_KEY set; skipping key setup (non-interactive mode).${NC}"
151+
} else {
152+
Write-Host "go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key."
153+
Write-Host ""
154+
$apiKey = Read-Host "paste your API key here"
155+
Write-Host ""
156+
}
141157
}
142158

143159
if ($skipApiKeySetup) {
@@ -155,7 +171,7 @@ if ($skipApiKeySetup) {
155171
}
156172

157173
# ASCII Art Welcome
158-
Clear-Host
174+
if (-not $nonInteractive) { Clear-Host }
159175
Write-Host ""
160176
Write-Host "${NC}"
161177
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
@@ -178,10 +194,14 @@ Write-Host ""
178194
Write-Host ""
179195
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
180196
Write-Host ""
181-
Write-Host " would you like to get a quick intro to ***plain specification language?"
182-
Write-Host ""
183-
$walkthroughChoice = Read-Host " [Y/n]"
184-
Write-Host ""
197+
if ($nonInteractive) {
198+
$walkthroughChoice = "n"
199+
} else {
200+
Write-Host " would you like to get a quick intro to ***plain specification language?"
201+
Write-Host ""
202+
$walkthroughChoice = Read-Host " [Y/n]"
203+
Write-Host ""
204+
}
185205

186206
# Determine script directory for local execution
187207
$ScriptDir = ""
@@ -225,27 +245,31 @@ if ($walkthroughChoice -notmatch '^[Nn]$') {
225245
}
226246

227247
# Download examples step
228-
Clear-Host
229-
Write-Host ""
230-
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
231-
Write-Host " ${YELLOW}${BOLD}Example Projects${NC}"
232-
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
233-
Write-Host ""
234-
Write-Host " we've prepared some example Plain projects for you"
235-
Write-Host " to explore and experiment with."
236-
Write-Host ""
237-
Write-Host " would you like to download them?"
238-
Write-Host ""
239-
$downloadExamples = Read-Host " [Y/n]"
240-
Write-Host ""
248+
if ($nonInteractive) {
249+
$downloadExamples = "n"
250+
} else {
251+
Clear-Host
252+
Write-Host ""
253+
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
254+
Write-Host " ${YELLOW}${BOLD}Example Projects${NC}"
255+
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
256+
Write-Host ""
257+
Write-Host " we've prepared some example Plain projects for you"
258+
Write-Host " to explore and experiment with."
259+
Write-Host ""
260+
Write-Host " would you like to download them?"
261+
Write-Host ""
262+
$downloadExamples = Read-Host " [Y/n]"
263+
Write-Host ""
264+
}
241265

242266
# Run examples download if user agrees
243267
if ($downloadExamples -notmatch '^[Nn]$') {
244268
Invoke-SubScript "examples.ps1"
245269
}
246270

247271
# Final message
248-
Clear-Host
272+
if (-not $nonInteractive) { Clear-Host }
249273
Write-Host ""
250274
Write-Host "${GRAY}────────────────────────────────────────────${NC}"
251275
Write-Host " ${YELLOW}${BOLD}You're all set!${NC}"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,4 @@ exclude = [
109109
[tool.pytest.ini_options]
110110
pythonpath = ["src"]
111111
testpaths = ["tests"]
112-
norecursedirs = ["tests/data"]
112+
norecursedirs = ["tests/data", "tests/e2e"]

pytest.ini

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ testpaths = tests
33
python_files = test_*.py
44
python_classes = Test*
55
python_functions = test_*
6-
# Ignore test data directory (contains fixture files, not actual tests)
7-
norecursedirs = tests/data
6+
# Ignore test data directory (contains fixture files, not actual tests).
7+
# exclude e2e tests from discovered tests because it requires Docker
8+
norecursedirs = tests/data tests/e2e

0 commit comments

Comments
 (0)