Compare commits

...

2 Commits

Author SHA1 Message Date
dependabot[bot] ed46ac0b40 chore(deps): bump the actions group with 6 updates
Bumps the actions group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.6.4` | `0.8.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.1` | `7.0.2` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `8.0.1` | `8.0.2` |
| [actions/setup-node](https://github.com/actions/setup-node) | `7.0.0` | `7.1.0` |
| [github/codeql-action/init](https://github.com/github/codeql-action) | `4.38.2` | `4.39.1` |
| [github/codeql-action/analyze](https://github.com/github/codeql-action) | `4.38.2` | `4.39.1` |


Updates `zizmorcore/zizmor-action` from 0.6.4 to 0.8.0
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/cc914d7f3750a2d13d75c7f184a1060aa0e9d482...53290badfa369cb0bf7ad16342cb62c2fa47ac7b)

Updates `actions/upload-artifact` from 7.0.1 to 7.0.2
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/043fb46d1a93c77aae656e7c1c64a875d1fc6a0a...cf430e030ddbb5b0abf93d22962f4752f3646cd9)

Updates `actions/download-artifact` from 8.0.1 to 8.0.2
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c...9000827ccba6bdab643e8b6fd33ac0654aef8333)

Updates `actions/setup-node` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1)

Updates `github/codeql-action/init` from 4.38.2 to 4.39.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...9b3254085494b55a0f7c4c2b3d2d52cc712ce370)

Updates `github/codeql-action/analyze` from 4.38.2 to 4.39.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...9b3254085494b55a0f7c4c2b3d2d52cc712ce370)

---
updated-dependencies:
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: 8.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/setup-node
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action/init
  dependency-version: 4.39.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.39.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-01 01:11:26 +00:00
Oliver Kieselbach 6901f6f682 Install Progress on phones: the green detection pill moves into Details, red and amber shorten (#194) 2026-10-31 08:50:27 +01:00
11 changed files with 124 additions and 48 deletions
+1 -1
View File
@@ -105,7 +105,7 @@ jobs:
# the local install so the gate and the pre-commit run agree on the finding set.
# Informational findings (template expansion of our own step outputs in pwsh) are
# visible locally but do not fail the gate.
- uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
- uses: zizmorcore/zizmor-action@53290badfa369cb0bf7ad16342cb62c2fa47ac7b # v0.8.0
with:
version: 1.30.1
min-severity: low
+4 -4
View File
@@ -247,7 +247,7 @@ jobs:
Get-ChildItem $outDir | ForEach-Object { Write-Host "$($_.Name): $([math]::Round($_.Length / 1MB, 2)) MB" }
- name: Upload unsigned build output
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: agent-unsigned
path: ${{ runner.temp }}/agent-unsigned
@@ -293,7 +293,7 @@ jobs:
run: ./.github/scripts/Get-Endpoints.ps1 -ExportToGitHubEnv
- name: Download unsigned build output
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: agent-unsigned
path: ${{ runner.temp }}/agent-unsigned
@@ -790,13 +790,13 @@ jobs:
staging/agent/AutopilotMonitor.SummaryDialog.exe
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: AutopilotMonitor-Agent-v${{ needs.reserve.outputs.version }}
path: ${{ steps.artifact.outputs.versioned_zip_release }}
- name: Upload version metadata
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: version-metadata
path: ${{ env.MANIFEST_NAME }}
+6 -6
View File
@@ -127,7 +127,7 @@ jobs:
Write-Host "$env:RUNNER_SCRIPT : Valid, timestamped, signer $($sig.SignerCertificate.Subject.Split(',')[0])"
- name: Upload signed loader
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: bootstrap-loader-signed
path: ${{ env.RUNNER_SCRIPT }}
@@ -148,7 +148,7 @@ jobs:
persist-credentials: false
- name: Download signed loader
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: bootstrap-loader-signed
path: ${{ runner.temp }}/loader
@@ -187,7 +187,7 @@ jobs:
Write-Host "Built $env:STABLE_MSI ($([math]::Round((Get-Item $env:STABLE_MSI).Length / 1KB)) KB)"
- name: Upload unsigned MSI
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: bootstrap-msi-unsigned
path: ${{ env.STABLE_MSI }}
@@ -215,7 +215,7 @@ jobs:
persist-credentials: false
- name: Download unsigned MSI
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: bootstrap-msi-unsigned
path: ${{ runner.temp }}/msi
@@ -310,7 +310,7 @@ jobs:
"version=$version" >> $env:GITHUB_OUTPUT
- name: Download unsigned MSI
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: bootstrap-msi-unsigned
path: ${{ runner.temp }}/msi
@@ -442,7 +442,7 @@ jobs:
subject-path: ${{ env.STABLE_MSI }}
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: AutopilotMonitor-Bootstrap-v${{ steps.version.outputs.version }}
path: ${{ env.STABLE_MSI }}
+5 -5
View File
@@ -134,7 +134,7 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
cache: npm
@@ -176,7 +176,7 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
cache: npm
@@ -222,7 +222,7 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
@@ -245,7 +245,7 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
@@ -276,7 +276,7 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
cache: npm
+2 -2
View File
@@ -112,7 +112,7 @@ jobs:
dotnet-version: '10.0.x'
- name: Initialize CodeQL
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -123,6 +123,6 @@ jobs:
run: dotnet build AutopilotMonitor.sln --configuration Release
- name: Analyze
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
category: /language:${{ matrix.language }}
+2 -2
View File
@@ -32,7 +32,7 @@ jobs:
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
@@ -66,7 +66,7 @@ jobs:
# `git push` needs.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
+2 -2
View File
@@ -99,7 +99,7 @@ jobs:
run: tar -czf "$RUNNER_TEMP/backend-publish.tgz" -C publish .
- name: Upload publish output
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: backend-publish
path: ${{ runner.temp }}/backend-publish.tgz
@@ -128,7 +128,7 @@ jobs:
run: ./.github/scripts/Get-Endpoints.ps1 -ExportToGitHubEnv
- name: Download publish output
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: backend-publish
path: ${{ runner.temp }}/backend-artifact
+4 -4
View File
@@ -74,7 +74,7 @@ jobs:
id: docs
run: echo "sha=$(git -C whats-new-docs rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
cache: npm
@@ -149,7 +149,7 @@ jobs:
sha256sum "$archive"
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: portal-${{ github.sha }}
path: ${{ steps.package.outputs.archive }}
@@ -170,7 +170,7 @@ jobs:
persist-credentials: false
- name: Download build artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: portal-${{ github.sha }}
path: ${{ runner.temp }}/portal
@@ -215,7 +215,7 @@ jobs:
run: ./.github/scripts/Get-Endpoints.ps1 -ExportToGitHubEnv
- name: Download build artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: portal-${{ github.sha }}
path: ${{ runner.temp }}/portal
+1 -1
View File
@@ -150,7 +150,7 @@ jobs:
# when someone wants to look at the file.
- name: Upload signed scripts
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: signed-scripts
path: ${{ runner.temp }}/signed-scripts
@@ -47,6 +47,39 @@ function formatDuration(ms: number): string {
return `${hours}h ${remainingMinutes}m`;
}
interface DetectionBadge {
label: string;
/** Label below `sm`; null hides the pill there — it then appears in the row's Details only. */
phoneLabel: string | null;
tone: string;
title: string;
}
// IME's check right after the install, or after the restart the installer requested (D-392).
// Any result other than Detected/NotDetected is IME's DetectedDifferentVersion.
function postInstallDetectionBadge(result: string, afterReboot: boolean | undefined): DetectionBadge {
const check = `Intune's detection check right after the ${afterReboot ? "restart the installer requested" : "installer finished"}`;
if (result === "Detected") {
// Only confirms what the check icon and the green row already say, so on a phone it yields
// its room to the app name instead of squeezing it to a few letters.
return { label: "Detected after install", phoneLabel: null, tone: "bg-green-100 text-green-700", title: `${check}: the app was found.` };
}
if (result === "NotDetected") {
return {
label: "Not detected after install",
phoneLabel: "Not detected",
tone: "bg-red-200 text-red-800",
title: `${check}: the app was not found, so Intune counts the install as failed (0x87D1041C).`,
};
}
return {
label: "Different version detected",
phoneLabel: "Other version",
tone: "bg-amber-200 text-amber-700",
title: `${check}: a different version was found; Intune counts the app as installed.`,
};
}
export default function InstallProgress({ events, summaryStats, observedUntilMs = null, userPhaseBoundary = null }: InstallProgressProps) {
// Legacy-agent guard: split off app events replayed from a previous enrollment's IME log
// (newer agents suppress them at the source) so week-old installs never render as current.
@@ -263,6 +296,10 @@ function InstallItemRow({ item }: { item: InstallItem }) {
? liveElapsed.elapsedMs
: null;
// A failed row already says "Detection failed", so its NotDetected verdict is not repeated.
const detection = item.postInstallDetection && !(item.state === "Failed" && item.postInstallDetection === "NotDetected")
? postInstallDetectionBadge(item.postInstallDetection, item.postInstallAfterReboot)
: null;
// Session 080edee9 follow-up — only the genuine "no HRESULT available" timeout
// case wears the hedged orange treatment. Detection-failures and install-failures
@@ -343,29 +380,19 @@ function InstallItemRow({ item }: { item: InstallItem }) {
Uninstall
</span>
)}
{item.postInstallDetection && !(item.state === "Failed" && item.postInstallDetection === "NotDetected") && (
// IME's check right after the install (D-392); a failed row already says "Detection failed".
{detection && (
// The pill never shrinks (nowrap) while the name does, so on a phone a long label
// squeezed the app name to a few letters: short label there, or none at all.
<span
className={`text-xs px-2 py-0.5 rounded-full font-medium whitespace-nowrap ${
item.postInstallDetection === "Detected"
? "bg-green-100 text-green-700"
: item.postInstallDetection === "NotDetected"
? "bg-red-200 text-red-800"
: "bg-amber-200 text-amber-700"
}`}
title={`Intune's detection check right after the ${item.postInstallAfterReboot ? "restart the installer requested" : "installer finished"}: ${
item.postInstallDetection === "Detected"
? "the app was found."
: item.postInstallDetection === "NotDetected"
? "the app was not found, so Intune counts the install as failed (0x87D1041C)."
: "a different version was found; Intune counts the app as installed."
}`}
className={`text-xs px-2 py-0.5 rounded-full font-medium whitespace-nowrap ${detection.tone}${detection.phoneLabel == null ? " hidden sm:inline" : ""}`}
title={detection.title}
>
{item.postInstallDetection === "Detected"
? "Detected after install"
: item.postInstallDetection === "NotDetected"
? "Not detected after install"
: "Different version detected"}
{detection.phoneLabel == null ? detection.label : (
<>
<span className="sm:hidden">{detection.phoneLabel}</span>
<span className="hidden sm:inline">{detection.label}</span>
</>
)}
</span>
)}
{item.state === "Failed" && item.isLikelyStuck && (
@@ -516,6 +543,15 @@ function InstallItemRow({ item }: { item: InstallItem }) {
</div>
) : null}
{/* Phones: the row header shows the detection result short or not at all, and touch has
no hover tooltip — Details carries the full verdict. */}
{showDetails && detection && (
<div className="sm:hidden mt-3 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs">
<span className={`px-2 py-0.5 rounded-full font-medium whitespace-nowrap ${detection.tone}`}>{detection.label}</span>
<span className="text-gray-600">{detection.title}</span>
</div>
)}
{/* Event details (expandable) */}
{showDetails && item.eventData && (
<div className="mt-3 p-2 bg-gray-900 rounded text-xs text-gray-100 font-mono overflow-x-auto">
@@ -0,0 +1,40 @@
import { describe, it, expect } from "vitest";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import InstallProgress from "../InstallProgress";
import type { InstallEvent } from "@/lib/installProgress";
function evt(eventType: string, timestamp: string, data: Record<string, unknown>): InstallEvent {
return { eventType, timestamp, data };
}
function renderWithCheckAfterInstall(postInstallDetection: string): string {
return renderToStaticMarkup(
createElement(InstallProgress, {
events: [
evt("app_install_started", "2026-10-21T16:40:00Z", { appName: "Contoso VPN" }),
evt("app_install_completed", "2026-10-21T16:42:39Z", { appName: "Contoso VPN", state: "Installed" }),
evt("app_post_install_detection", "2026-10-21T16:42:41Z", { appName: "Contoso VPN", postInstallDetection, afterReboot: "false" }),
],
}),
);
}
describe("InstallProgress — detection pill on narrow screens", () => {
it("hides the green confirmation below sm so the app name keeps its room", () => {
const html = renderWithCheckAfterInstall("Detected");
expect(html).toContain("bg-green-100 text-green-700 hidden sm:inline");
expect(html).toContain(">Detected after install</span>");
expect(html).not.toContain('class="sm:hidden"');
});
it("keeps the red and amber verdicts on phones, with a short label", () => {
const notDetected = renderWithCheckAfterInstall("NotDetected");
expect(notDetected).toContain('<span class="sm:hidden">Not detected</span>');
expect(notDetected).toContain('<span class="hidden sm:inline">Not detected after install</span>');
const otherVersion = renderWithCheckAfterInstall("DetectedDifferentVersion");
expect(otherVersion).toContain('<span class="sm:hidden">Other version</span>');
expect(otherVersion).toContain('<span class="hidden sm:inline">Different version detected</span>');
});
});