fix: resolve E2E settings + badge navigation failures #52
@@ -65,6 +65,39 @@ jobs:
|
|||||||
echo "::warning::Version mismatch — repo has $EXPECTED but Headlamp runs $DEPLOYED_VERSION. Tests may fail due to stale plugin."
|
echo "::warning::Version mismatch — repo has $EXPECTED but Headlamp runs $DEPLOYED_VERSION. Tests may fail due to stale plugin."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Build plugin
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Setup kubectl
|
||||||
|
uses: azure/setup-kubectl@v4
|
||||||
|
|
||||||
|
- name: Configure kubeconfig
|
||||||
|
env:
|
||||||
|
KUBECONFIG_DATA: ${{ secrets.KUBECONFIG }}
|
||||||
|
run: |
|
||||||
|
if [ -n "$KUBECONFIG_DATA" ]; then
|
||||||
|
mkdir -p ~/.kube
|
||||||
|
echo "$KUBECONFIG_DATA" | base64 -d > ~/.kube/config
|
||||||
|
chmod 600 ~/.kube/config
|
||||||
|
elif [ -f /var/run/secrets/kubernetes.io/serviceaccount/token ]; then
|
||||||
|
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||||
|
CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
|
||||||
|
kubectl config set-cluster in-cluster --server=https://kubernetes.default.svc --certificate-authority="$CA_CERT"
|
||||||
|
kubectl config set-credentials sa-user --token="$SA_TOKEN"
|
||||||
|
kubectl config set-context in-cluster --cluster=in-cluster --user=sa-user --namespace="$NAMESPACE"
|
||||||
|
kubectl config use-context in-cluster
|
||||||
|
fi
|
||||||
|
kubectl version --client
|
||||||
|
kubectl cluster-info || echo "::warning::Cannot reach cluster API — deploy step may fail"
|
||||||
|
|
||||||
|
- name: Deploy plugin to Headlamp
|
||||||
|
env:
|
||||||
|
HEADLAMP_URL: ${{ secrets.HEADLAMP_URL || 'http://headlamp.kube-system.svc.cluster.local' }}
|
||||||
|
HEADLAMP_NS: ${{ secrets.HEADLAMP_NS || 'kube-system' }}
|
||||||
|
HEADLAMP_PLUGIN_DIR: ${{ secrets.HEADLAMP_PLUGIN_DIR || '/headlamp/static-plugins/polaris' }}
|
||||||
|
run: ./scripts/deploy-plugin-to-headlamp.sh
|
||||||
|
|
||||||
- name: Install Playwright browsers
|
- name: Install Playwright browsers
|
||||||
run: npx playwright install --with-deps chromium
|
run: npx playwright install --with-deps chromium
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -6,5 +6,5 @@ COPY src/ src/
|
|||||||
RUN npx @kinvolk/headlamp-plugin build
|
RUN npx @kinvolk/headlamp-plugin build
|
||||||
|
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
COPY --from=build /app/dist/ /plugins/headlamp-polaris-plugin/
|
COPY --from=build /app/dist/ /plugins/polaris/
|
||||||
COPY --from=build /app/package.json /plugins/headlamp-polaris-plugin/
|
COPY --from=build /app/package.json /plugins/polaris/
|
||||||
|
|||||||
Executable
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploy the built plugin to a live Headlamp instance via kubectl.
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# - kubectl configured with access to the Headlamp namespace
|
||||||
|
# - Plugin already built (npm run build → dist/)
|
||||||
|
#
|
||||||
|
# Environment variables (all optional, with defaults):
|
||||||
|
# HEADLAMP_URL — Headlamp URL for readiness check
|
||||||
|
# HEADLAMP_NS — Kubernetes namespace (default: kube-system)
|
||||||
|
# HEADLAMP_PLUGIN_DIR — Plugin path inside the pod (default: /headlamp/static-plugins/polaris)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# npm run build
|
||||||
|
# ./scripts/deploy-plugin-to-headlamp.sh
|
||||||
|
#
|
||||||
|
# Intended to be called from the E2E workflow before running Playwright tests,
|
||||||
|
# so that E2E always tests the current commit's plugin code rather than whatever
|
||||||
|
# was previously deployed.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HEADLAMP_URL="${HEADLAMP_URL:-http://headlamp.kube-system.svc.cluster.local}"
|
||||||
|
HEADLAMP_NS="${HEADLAMP_NS:-kube-system}"
|
||||||
|
HEADLAMP_PLUGIN_DIR="${HEADLAMP_PLUGIN_DIR:-/headlamp/static-plugins/polaris}"
|
||||||
|
|
||||||
|
if [ ! -d "dist" ]; then
|
||||||
|
echo "Error: dist/ not found. Run 'npm run build' first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the Headlamp pod
|
||||||
|
POD=$(kubectl get pod -n "$HEADLAMP_NS" -l app.kubernetes.io/name=headlamp \
|
||||||
|
-o jsonpath='{.items[0].metadata.name}')
|
||||||
|
echo "Headlamp pod: $POD"
|
||||||
|
|
||||||
|
# Remove stale plugin and copy current build
|
||||||
|
kubectl exec -n "$HEADLAMP_NS" "$POD" -c headlamp -- \
|
||||||
|
rm -rf "$HEADLAMP_PLUGIN_DIR" 2>/dev/null || true
|
||||||
|
kubectl cp dist/. "$HEADLAMP_NS/$POD:$HEADLAMP_PLUGIN_DIR" -c headlamp
|
||||||
|
|
||||||
|
# Copy package.json so Headlamp can read plugin metadata
|
||||||
|
kubectl cp package.json "$HEADLAMP_NS/$POD:$HEADLAMP_PLUGIN_DIR/package.json" -c headlamp
|
||||||
|
|
||||||
|
# Verify the copy
|
||||||
|
echo "Deployed files:"
|
||||||
|
kubectl exec -n "$HEADLAMP_NS" "$POD" -c headlamp -- \
|
||||||
|
ls -la "$HEADLAMP_PLUGIN_DIR"
|
||||||
|
|
||||||
|
# Restart the Headlamp process to reload plugins.
|
||||||
|
# Killing PID 1 restarts the container without replacing the pod,
|
||||||
|
# so the emptyDir volume (and our copied files) is preserved.
|
||||||
|
echo "Restarting Headlamp process..."
|
||||||
|
kubectl exec -n "$HEADLAMP_NS" "$POD" -c headlamp -- kill 1 || true
|
||||||
|
|
||||||
|
# Wait for Headlamp to come back
|
||||||
|
echo "Waiting for Headlamp to restart..."
|
||||||
|
sleep 10
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 "$HEADLAMP_URL" || true)
|
||||||
|
if [ "$HTTP_CODE" = "200" ]; then
|
||||||
|
echo "Headlamp is ready"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo " attempt $i/30 — HTTP $HTTP_CODE"
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Error: Headlamp did not recover after plugin deploy" >&2
|
||||||
|
exit 1
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { K8s, Router } from '@kinvolk/headlamp-plugin/lib';
|
import { K8s } from '@kinvolk/headlamp-plugin/lib';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
@@ -36,7 +36,8 @@ export default function AppBarScoreBadge() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
history.push(Router.createRouteURL('polaris', { cluster: cluster ?? '' }));
|
const prefix = cluster ? `/c/${cluster}` : '';
|
||||||
|
history.push(`${prefix}/polaris`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ registerRoute({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Register plugin settings
|
// Register plugin settings
|
||||||
registerPluginSettings('headlamp-polaris', PolarisSettings, true);
|
registerPluginSettings('polaris', PolarisSettings, true);
|
||||||
|
|
||||||
// Register details view section for supported controller types
|
// Register details view section for supported controller types
|
||||||
registerDetailsViewSection(({ resource }) => {
|
registerDetailsViewSection(({ resource }) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user