Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6965103113 | |||
| 0659afcf6e | |||
| 808f60ad88 | |||
| ade6bf93a7 | |||
| 10ed01439c |
@@ -55,6 +55,23 @@ jobs:
|
|||||||
if: env.SKIP_BUILD != 'true'
|
if: env.SKIP_BUILD != 'true'
|
||||||
run: npx @kinvolk/headlamp-plugin package
|
run: npx @kinvolk/headlamp-plugin package
|
||||||
|
|
||||||
|
- name: Validate tarball name matches package.json
|
||||||
|
if: env.SKIP_BUILD != 'true'
|
||||||
|
run: |
|
||||||
|
PACKAGE_NAME=$(jq -r '.name' package.json)
|
||||||
|
VERSION=${GITHUB_REF_NAME#v}
|
||||||
|
EXPECTED_TARBALL="${PACKAGE_NAME}-${VERSION}.tar.gz"
|
||||||
|
ACTUAL_TARBALL=$(ls *.tar.gz)
|
||||||
|
|
||||||
|
if [ "$EXPECTED_TARBALL" != "$ACTUAL_TARBALL" ]; then
|
||||||
|
echo "::error::Tarball name mismatch!"
|
||||||
|
echo "Expected: $EXPECTED_TARBALL"
|
||||||
|
echo "Actual: $ACTUAL_TARBALL"
|
||||||
|
echo "Update workflow to use correct tarball name pattern"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✓ Tarball name validation passed: $ACTUAL_TARBALL"
|
||||||
|
|
||||||
- name: Compute tarball checksum
|
- name: Compute tarball checksum
|
||||||
if: env.SKIP_BUILD != 'true'
|
if: env.SKIP_BUILD != 'true'
|
||||||
run: |
|
run: |
|
||||||
@@ -65,17 +82,25 @@ jobs:
|
|||||||
echo "Tarball: $TARBALL"
|
echo "Tarball: $TARBALL"
|
||||||
echo "Checksum: sha256:$CHECKSUM"
|
echo "Checksum: sha256:$CHECKSUM"
|
||||||
|
|
||||||
- name: Create GitHub release and upload tarball
|
- name: Create draft release and upload tarball
|
||||||
if: env.SKIP_BUILD != 'true'
|
if: env.SKIP_BUILD != 'true'
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: ${{ env.TARBALL }}
|
files: ${{ env.TARBALL }}
|
||||||
fail_on_unmatched_files: true
|
fail_on_unmatched_files: true
|
||||||
draft: false
|
draft: true
|
||||||
prerelease: false
|
prerelease: false
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Publish release
|
||||||
|
if: env.SKIP_BUILD != 'true'
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
draft: false
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Update metadata and align tag
|
- name: Update metadata and align tag
|
||||||
if: env.SKIP_BUILD != 'true'
|
if: env.SKIP_BUILD != 'true'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
version: 0.3.8
|
version: 0.3.9
|
||||||
name: headlamp-polaris-plugin
|
name: headlamp-polaris-plugin
|
||||||
displayName: Polaris
|
displayName: Polaris
|
||||||
createdAt: "2026-02-05T19:00:00Z"
|
createdAt: "2026-02-05T19:00:00Z"
|
||||||
@@ -28,7 +28,7 @@ maintainers:
|
|||||||
- name: cpfarhood
|
- name: cpfarhood
|
||||||
email: "chris@farhood.org"
|
email: "chris@farhood.org"
|
||||||
annotations:
|
annotations:
|
||||||
headlamp/plugin/archive-url: "https://github.com/cpfarhood/headlamp-polaris-plugin/releases/download/v0.3.8/polaris-0.3.8.tar.gz"
|
headlamp/plugin/archive-url: "https://github.com/cpfarhood/headlamp-polaris-plugin/releases/download/v0.3.9/polaris-0.3.9.tar.gz"
|
||||||
headlamp/plugin/version-compat: ">=0.26"
|
headlamp/plugin/version-compat: ">=0.26"
|
||||||
headlamp/plugin/archive-checksum: sha256:109720d9ab5cf425fbf18619371b34f4eb555983b2877cce2eee0de2ce862a67
|
headlamp/plugin/archive-checksum: sha256:4447bff847623dbab0d0cde739f17e5b2888bf95e1f152fa217274004775823d
|
||||||
headlamp/plugin/distro-compat: in-cluster
|
headlamp/plugin/distro-compat: in-cluster
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "polaris",
|
"name": "polaris",
|
||||||
"version": "0.3.8",
|
"version": "0.3.9",
|
||||||
"description": "Headlamp plugin for Fairwinds Polaris audit results",
|
"description": "Headlamp plugin for Fairwinds Polaris audit results",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -95,126 +95,133 @@ function NamespaceDetailPanel({ namespace, onClose }: NamespaceDetailPanelProps)
|
|||||||
return countsPerResource.get(`${row.Namespace}/${row.Kind}/${row.Name}`) ?? resourceCounts(row);
|
return countsPerResource.get(`${row.Namespace}/${row.Kind}/${row.Name}`) ?? resourceCounts(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate a unique class name for this drawer to avoid conflicts
|
||||||
|
const drawerClass = `polaris-namespace-drawer-${namespace}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
style={{
|
<style>
|
||||||
position: 'fixed',
|
{`
|
||||||
right: 0,
|
.${drawerClass} {
|
||||||
top: 0,
|
position: fixed;
|
||||||
bottom: 0,
|
right: 0;
|
||||||
width: '1000px',
|
top: 0;
|
||||||
backgroundColor: 'var(--mui-palette-background-paper)',
|
bottom: 0;
|
||||||
color: 'var(--mui-palette-text-primary)',
|
width: 1000px;
|
||||||
boxShadow: '-2px 0 8px rgba(0,0,0,0.15)',
|
background-color: var(--mui-palette-background-default, #fafafa);
|
||||||
overflowY: 'auto',
|
color: var(--mui-palette-text-primary);
|
||||||
zIndex: 1200,
|
box-shadow: -2px 0 8px rgba(0,0,0,0.15);
|
||||||
padding: '20px',
|
overflow-y: auto;
|
||||||
opacity: 1,
|
z-index: 1200;
|
||||||
}}
|
padding: 20px;
|
||||||
>
|
}
|
||||||
<div
|
`}
|
||||||
style={{
|
</style>
|
||||||
marginBottom: '20px',
|
<div className={drawerClass}>
|
||||||
display: 'flex',
|
<div
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h2 style={{ margin: 0, color: 'var(--mui-palette-text-primary)' }}>
|
|
||||||
Polaris — {namespace}
|
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
marginBottom: '20px',
|
||||||
background: 'transparent',
|
display: 'flex',
|
||||||
fontSize: '24px',
|
justifyContent: 'space-between',
|
||||||
cursor: 'pointer',
|
alignItems: 'center',
|
||||||
padding: '0 8px',
|
|
||||||
color: 'var(--mui-palette-text-primary)',
|
|
||||||
}}
|
}}
|
||||||
aria-label="Close panel"
|
|
||||||
>
|
>
|
||||||
×
|
<h2 style={{ margin: 0, color: 'var(--mui-palette-text-primary)' }}>
|
||||||
</button>
|
Polaris — {namespace}
|
||||||
|
</h2>
|
||||||
|
<button
|
||||||
|
onClick={onClose}
|
||||||
|
style={{
|
||||||
|
border: 'none',
|
||||||
|
background: 'transparent',
|
||||||
|
fontSize: '24px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: '0 8px',
|
||||||
|
color: 'var(--mui-palette-text-primary)',
|
||||||
|
}}
|
||||||
|
aria-label="Close panel"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SectionBox title="External">
|
||||||
|
<NameValueTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
name: 'Polaris Dashboard',
|
||||||
|
value: (
|
||||||
|
<a href={getPolarisProxyUrl()} target="_blank" rel="noopener noreferrer">
|
||||||
|
View in Polaris Dashboard
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SectionBox>
|
||||||
|
|
||||||
|
<SectionBox title="Namespace Score">
|
||||||
|
<NameValueTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
name: 'Score',
|
||||||
|
value: <StatusLabel status={status}>{score}%</StatusLabel>,
|
||||||
|
},
|
||||||
|
{ name: 'Total Checks', value: String(counts.total) },
|
||||||
|
{
|
||||||
|
name: 'Pass',
|
||||||
|
value: <StatusLabel status="success">{counts.pass}</StatusLabel>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Warning',
|
||||||
|
value: <StatusLabel status="warning">{counts.warning}</StatusLabel>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Danger',
|
||||||
|
value: <StatusLabel status="error">{counts.danger}</StatusLabel>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Skipped',
|
||||||
|
value: (
|
||||||
|
<span title="Only counts checks with Severity=ignore. Annotation-based exemptions are not included.">
|
||||||
|
{counts.skipped}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SectionBox>
|
||||||
|
|
||||||
|
<SectionBox title="Resources">
|
||||||
|
<SimpleTable
|
||||||
|
columns={[
|
||||||
|
{ label: 'Name', getter: (row: Result) => row.Name },
|
||||||
|
{ label: 'Kind', getter: (row: Result) => row.Kind },
|
||||||
|
{
|
||||||
|
label: 'Pass',
|
||||||
|
getter: (row: Result) => (
|
||||||
|
<StatusLabel status="success">{getResourceCounts(row).pass}</StatusLabel>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Warning',
|
||||||
|
getter: (row: Result) => (
|
||||||
|
<StatusLabel status="warning">{getResourceCounts(row).warning}</StatusLabel>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Danger',
|
||||||
|
getter: (row: Result) => (
|
||||||
|
<StatusLabel status="error">{getResourceCounts(row).danger}</StatusLabel>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
data={results}
|
||||||
|
emptyMessage={`No resources found in namespace "${namespace}".`}
|
||||||
|
/>
|
||||||
|
</SectionBox>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
<SectionBox title="External">
|
|
||||||
<NameValueTable
|
|
||||||
rows={[
|
|
||||||
{
|
|
||||||
name: 'Polaris Dashboard',
|
|
||||||
value: (
|
|
||||||
<a href={getPolarisProxyUrl()} target="_blank" rel="noopener noreferrer">
|
|
||||||
View in Polaris Dashboard
|
|
||||||
</a>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SectionBox>
|
|
||||||
|
|
||||||
<SectionBox title="Namespace Score">
|
|
||||||
<NameValueTable
|
|
||||||
rows={[
|
|
||||||
{
|
|
||||||
name: 'Score',
|
|
||||||
value: <StatusLabel status={status}>{score}%</StatusLabel>,
|
|
||||||
},
|
|
||||||
{ name: 'Total Checks', value: String(counts.total) },
|
|
||||||
{
|
|
||||||
name: 'Pass',
|
|
||||||
value: <StatusLabel status="success">{counts.pass}</StatusLabel>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Warning',
|
|
||||||
value: <StatusLabel status="warning">{counts.warning}</StatusLabel>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Danger',
|
|
||||||
value: <StatusLabel status="error">{counts.danger}</StatusLabel>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Skipped',
|
|
||||||
value: (
|
|
||||||
<span title="Only counts checks with Severity=ignore. Annotation-based exemptions are not included.">
|
|
||||||
{counts.skipped}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</SectionBox>
|
|
||||||
|
|
||||||
<SectionBox title="Resources">
|
|
||||||
<SimpleTable
|
|
||||||
columns={[
|
|
||||||
{ label: 'Name', getter: (row: Result) => row.Name },
|
|
||||||
{ label: 'Kind', getter: (row: Result) => row.Kind },
|
|
||||||
{
|
|
||||||
label: 'Pass',
|
|
||||||
getter: (row: Result) => (
|
|
||||||
<StatusLabel status="success">{getResourceCounts(row).pass}</StatusLabel>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Warning',
|
|
||||||
getter: (row: Result) => (
|
|
||||||
<StatusLabel status="warning">{getResourceCounts(row).warning}</StatusLabel>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Danger',
|
|
||||||
getter: (row: Result) => (
|
|
||||||
<StatusLabel status="error">{getResourceCounts(row).danger}</StatusLabel>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
data={results}
|
|
||||||
emptyMessage={`No resources found in namespace "${namespace}".`}
|
|
||||||
/>
|
|
||||||
</SectionBox>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user