Skip to content

Commit 60b1c51

Browse files
authored
Merge branch 'main' into patch-2
2 parents 3460fd3 + b228929 commit 60b1c51

File tree

225 files changed

+31024
-5695
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

225 files changed

+31024
-5695
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#!/usr/bin/env node
2+
3+
/*
4+
* Copyright 2025 The Kubernetes Authors
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/**
20+
* Generate the release coordination issue body or release notes template
21+
* Usage:
22+
* node generate-release-issue-body.js issue <releaseName> <prevTag> <author>
23+
* node generate-release-issue-body.js release-notes
24+
*/
25+
26+
const mode = process.argv[2];
27+
28+
if (mode === 'release-notes') {
29+
const releaseNotesTemplate = `## ✨ Enhancements:
30+
* Feature 1
31+
* Feature 2
32+
33+
## 🐞 Bug fixes
34+
* Fix 1
35+
* Fix 2
36+
37+
## 💻 Development
38+
* Development experience related change 1
39+
* Development experience related change 2
40+
41+
## 📖 Documentation
42+
* Docs change 1
43+
* Docs change 2`;
44+
45+
console.log(releaseNotesTemplate);
46+
process.exit(0);
47+
}
48+
49+
if (mode !== 'issue') {
50+
console.error('Usage:');
51+
console.error(' node generate-release-issue-body.js issue <releaseName> <prevTag> <author>');
52+
console.error(' node generate-release-issue-body.js release-notes');
53+
process.exit(1);
54+
}
55+
56+
const releaseName = process.argv[3];
57+
const prevTag = process.argv[4];
58+
const author = process.argv[5];
59+
60+
if (!releaseName || !prevTag || !author) {
61+
console.error('Usage: node generate-release-issue-body.js issue <releaseName> <prevTag> <author>');
62+
process.exit(1);
63+
}
64+
65+
const testBattery = `# Release testing
66+
67+
NOTE: the release isn't frozen yet for testing.
68+
69+
Please write a comment if you're going to test an item and if you've completed testing an item.
70+
71+
- [ ] **Test web sockets**
72+
- Run the app in static server mode (\`./backend/headlamp-server -static-html-dir ./frontend/build...\`)
73+
- Open the pods list view
74+
- Delete a pod using kubectl
75+
- Verify that the list reflects the changes
76+
77+
- [ ] **App: Run with plugins**
78+
- Build app with plugins: \`make && make app\`
79+
- Run the app (UI should load in less than 1 minute)
80+
- Verify plugins are present: App Catalog, Prometheus, App Catalog
81+
82+
- [ ] **App: Test Prometheus plugin**
83+
- Run the app
84+
- Go to the Pods page and choose a pod
85+
- Verify the Prometheus plugin shows at the top and displays correctly
86+
87+
- [ ] **Image: Test Prometheus plugin**
88+
- Run headlamp from image
89+
- Go to the Pods page and choose a pod
90+
- Verify the Prometheus plugin shows at the top and displays correctly
91+
92+
- [ ] **App: Test Plugin Catalog**
93+
- Run the app
94+
- Verify the Plugin Catalog sidebar item is available and open it
95+
- Verify plugins appear from ArtifactHub
96+
- Install a plugin
97+
- Verify the plugin shows as installed
98+
- Delete the plugin
99+
- Verify the plugin shows as available to install
100+
101+
- [ ] **Test creating a resource through edit button**
102+
- Open Headlamp via app or image
103+
- Choose a cluster where you have admin rights
104+
- Click Create (bottom left), add a resource (e.g., ConfigMap), and apply
105+
- Verify the resource is created
106+
107+
- [ ] **Check Workloads page**
108+
- Open Headlamp via app or image
109+
- Go to the Workloads page of a cluster with diverse resource types
110+
- Verify resources and top charts display correctly
111+
112+
- [ ] **Check cluster renaming**
113+
- Open Headlamp via app or image
114+
- Open cluster settings
115+
- Rename the cluster
116+
- Verify the cluster name changed
117+
- Reload the app
118+
- Verify the new name persists
119+
120+
- [ ] **App: Check running on Mac**
121+
- Open app on Mac
122+
- Verify it loaded in less than 30 seconds
123+
124+
- [ ] **App: Check running on Windows**
125+
- Open app on Windows
126+
- Verify it loaded in less than 30 seconds
127+
128+
- [ ] **App: Check running on Linux**
129+
- Open app on Linux
130+
- Verify it loaded in less than 30 seconds
131+
132+
- [ ] **App: Load more than one cluster**
133+
- Open app
134+
- Add a new cluster from a kubeconfig file
135+
- Add another cluster from another kubeconfig file
136+
137+
- [ ] **Flatpak: Install a plugin**
138+
- Install a plugin from the app catalog
139+
- Verify it doesn't fail on cross-device linking
140+
141+
- [ ] **App: Load kubeconfig with context != cluster name**
142+
- Open app
143+
- Click Add Cluster
144+
- Choose a kubeconfig where a cluster name differs from the context name
145+
- Verify the cluster loads successfully
146+
147+
- [ ] **Allowed Namespaces**
148+
- Open Headlamp in any flavor
149+
- Configure allowed namespaces in cluster settings
150+
- Verify views honor allowed namespaces
151+
- Verify the map honors allowed namespaces
152+
153+
- [ ] **Create resources in the intended cluster**
154+
- Reproduce: "Create dialog doesn't update cluster when it's changed" (Issue #2441)
155+
- Verify resource creation targets the intended cluster
156+
157+
- [ ] **Check these plugins have settings**
158+
- Build a new app
159+
- Go to Settings > Plugins
160+
- Click each plugin to verify settings render
161+
- Plugins: Prometheus, App catalog, Plugin catalog
162+
`;
163+
164+
const releaseNotesTemplate = `## Release Notes
165+
166+
Please fill in the release notes below in the following format and then copy them to the release draft:
167+
168+
### ✨ Enhancements:
169+
* Feature 1
170+
* Feature 2
171+
172+
### 🐞 Bug fixes
173+
* Fix 1
174+
* Fix 2
175+
176+
### 💻 Development
177+
* Development experience related change 1
178+
* Development experience related change 2
179+
180+
### 📖 Documentation
181+
* Docs change 1
182+
* Docs change 2
183+
`;
184+
185+
const issueBody = `${testBattery}
186+
187+
---
188+
189+
## Changelog
190+
191+
@${author}, please run the following command to generate the changelog and paste it here:
192+
193+
\`\`\`bash
194+
git log --oneline --cherry --topo-order ${prevTag}..HEAD
195+
\`\`\`
196+
197+
---
198+
199+
${releaseNotesTemplate}
200+
`;
201+
202+
console.log(issueBody);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Build and upload embedded binaries
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
buildBranch:
7+
description: 'Headlamp ref/branch/tag'
8+
required: true
9+
default: 'main'
10+
version:
11+
description: 'Version for the binaries (defaults to app/package.json version)'
12+
required: false
13+
default: ''
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
build-embedded:
20+
permissions:
21+
actions: write # needed to upload artifacts
22+
contents: read
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
26+
with:
27+
ref: ${{ github.event.inputs.buildBranch }}
28+
- name: Setup nodejs
29+
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
30+
with:
31+
node-version: 20.x
32+
cache: 'npm'
33+
cache-dependency-path: |
34+
frontend/package-lock.json
35+
- uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
36+
with:
37+
go-version: '1.24.*'
38+
cache-dependency-path: |
39+
backend/go.sum
40+
- name: Get version
41+
id: get-version
42+
run: |
43+
if [ -n "${{ github.event.inputs.version }}" ]; then
44+
VERSION="${{ github.event.inputs.version }}"
45+
else
46+
VERSION=$(node -p "require('./app/package.json').version")
47+
fi
48+
echo "version=$VERSION" >> $GITHUB_OUTPUT
49+
echo "Building embedded binaries with version: $VERSION"
50+
- name: Build frontend
51+
run: |
52+
make frontend
53+
- name: Prepare backend for embedding
54+
run: |
55+
make backend-embed-prepare
56+
- name: Build embedded binaries
57+
run: |
58+
make backend-embed-all-compressed VERSION=${{ steps.get-version.outputs.version }}
59+
- name: Upload embedded binaries
60+
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
61+
with:
62+
name: embedded-binaries
63+
path: ./backend/dist/*.tar.gz
64+
if-no-files-found: error
65+
retention-days: 2
66+

.github/workflows/backend-test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ jobs:
7676
rm ~/.config/Headlamp/kubeconfigs/config
7777
shell: bash
7878

79+
- name: Run fuzz tests
80+
run: npm run backend:fuzz
81+
shell: bash
82+
7983
- name: Upload coverage report as artifact
8084
id: upload-artifact
8185
uses: actions/upload-artifact@84480863f228bb9747b473957fcc9e309aa96097 # v4.4.2

.github/workflows/build-container.yml

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,13 @@ jobs:
122122
cd ../../
123123
ls -laR .plugins
124124
- name: Remove unnecessary files
125-
if: steps.cache-image-restore2.outputs.cache-hit != 'true'
126125
run: |
127126
sudo rm -rf /usr/share/dotnet
128127
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
128+
sudo rm -rf /usr/local/lib/android
129+
sudo rm -rf /opt/ghc
130+
sudo rm -rf /usr/share/swift
131+
sudo apt-get clean
129132
- name: Build image
130133
if: steps.cache-image-restore2.outputs.cache-hit != 'true'
131134
run: |
@@ -137,8 +140,12 @@ jobs:
137140
- name: Import images to kind
138141
run: |
139142
export SHELL=/bin/bash
143+
# Load images into Cluster 1 (test)
140144
kind load docker-image ghcr.io/headlamp-k8s/headlamp-plugins-test:latest --name test
141145
kind load docker-image ghcr.io/headlamp-k8s/headlamp:latest --name test
146+
147+
# Load Headlamp image into Cluster 2 (test2) so it can run in-cluster tests there
148+
kind load docker-image ghcr.io/headlamp-k8s/headlamp:latest --name test2
142149
- name: Test .plugins folder
143150
if: steps.cache-image-restore2.outputs.cache-hit != 'true'
144151
run: |
@@ -231,6 +238,70 @@ jobs:
231238
else
232239
echo "Playwright tests passed successfully"
233240
fi
241+
- name: Deploy Headlamp in in-cluster mode and run TS API tests
242+
run: |
243+
# Reuse Cluster 2 context for in-cluster tests
244+
kubectl config use-context test2
245+
246+
# Setup service account and RBAC for Headlamp
247+
kubectl create serviceaccount headlamp --namespace kube-system || true
248+
kubectl create clusterrolebinding headlamp --serviceaccount=kube-system:headlamp --clusterrole=cluster-admin || true
249+
kubectl get serviceaccount headlamp -n kube-system
250+
251+
# Deploy Headlamp with in-cluster mode
252+
kubectl apply -f e2e-tests/kubernetes-headlamp-incluster-ci.yaml
253+
254+
echo "Waiting for headlamp deployment to be available (in-cluster)..."
255+
kubectl wait deployment -n kube-system headlamp --for condition=Available=True --timeout=120s
256+
kubectl get pods -n kube-system -l app.kubernetes.io/name=headlamp
257+
258+
echo "Checking headlamp pod status (in-cluster)..."
259+
kubectl logs -n kube-system -l app.kubernetes.io/name=headlamp --tail=50 || true
260+
261+
# Start port-forward in background
262+
echo "Starting port-forward to headlamp service (in-cluster)..."
263+
kubectl port-forward -n kube-system service/headlamp 8080:80 &
264+
PORT_FORWARD_PID=$!
265+
266+
# Wait for port-forward to be ready
267+
sleep 5
268+
269+
# Verify port-forward is working
270+
if ! kill -0 $PORT_FORWARD_PID 2>/dev/null; then
271+
echo "❌ Port-forward failed to start for in-cluster test"
272+
exit 1
273+
fi
274+
275+
export HEADLAMP_TEST_URL="http://localhost:8080"
276+
echo "In-cluster Headlamp URL: $HEADLAMP_TEST_URL"
277+
278+
# Get service account token for API checks
279+
echo "Getting service account token for in-cluster test..."
280+
export HEADLAMP_SA_TOKEN=$(kubectl create token headlamp --duration=1h -n kube-system)
281+
282+
if [ -z "$HEADLAMP_SA_TOKEN" ]; then
283+
echo "❌ Failed to get service account token for in-cluster test"
284+
kill $PORT_FORWARD_PID 2>/dev/null || true
285+
exit 1
286+
fi
287+
288+
echo "✅ Service account token obtained"
289+
echo "Running in-cluster API Playwright tests..."
290+
291+
# Run the TypeScript in-cluster API tests
292+
cd e2e-tests
293+
npm ci
294+
npx playwright install --with-deps
295+
npx playwright test tests/incluster-api.spec.ts
296+
EXIT_CODE=$?
297+
298+
# Cleanup port-forward
299+
kill $PORT_FORWARD_PID 2>/dev/null || true
300+
301+
if [ $EXIT_CODE -ne 0 ]; then
302+
echo "❌ In-cluster API tests failed with exit code $EXIT_CODE"
303+
exit $EXIT_CODE
304+
fi
234305
# Clear disk space by removing unnecessary files, apt files and uninstall some playwright dependencies
235306
- name: Clear Disk Space
236307
if: steps.cache-image-restore2.outputs.cache-hit != 'true'

0 commit comments

Comments
 (0)