Rework Build Site Agent binary UI with version auto-detect and rollback
Restructure the agent and tray binary blocks around an auto-detected current-release upload plus a separate legacy/rollback upload that stages a version without seizing current. Order staged versions by version number for the active-version dropdown, add a PE version detect route, and drop stale dev-status tags and manual-staging copy.
This commit is contained in:
@@ -160,7 +160,7 @@
|
||||
</section>
|
||||
|
||||
<!-- ====================================================================
|
||||
Adoption tool (spike)
|
||||
Adoption tool
|
||||
================================================================= -->
|
||||
<section class="settings-section">
|
||||
<h3>Adoption tool</h3>
|
||||
@@ -211,7 +211,7 @@
|
||||
</section>
|
||||
|
||||
<!-- ====================================================================
|
||||
Build site agent (placeholder)
|
||||
Build site agent
|
||||
================================================================= -->
|
||||
<section class="settings-section">
|
||||
<h3>Build site agent</h3>
|
||||
@@ -227,10 +227,9 @@
|
||||
</p>
|
||||
<p v-if="!agentstaged" class="field-hint">
|
||||
<strong>No agent binary is staged on this server.</strong> The package
|
||||
will still build with config and installer, but you must drop
|
||||
<code>shopdbagent.exe</code> beside them before deploying. Stage a
|
||||
prebuilt agent under <code>instance/siteagent/</code> to have it ship
|
||||
in the download.
|
||||
will still build with config and installer, but no agent will ship
|
||||
inside it. Upload a current release in the binary section below to
|
||||
have it included in every download.
|
||||
</p>
|
||||
|
||||
<label class="field-label" for="agent-baseurl">Server base URL</label>
|
||||
@@ -317,43 +316,112 @@
|
||||
class="binary-block"
|
||||
>
|
||||
<h4>{{ binary.label }}</h4>
|
||||
<p class="field-hint">
|
||||
Upload {{ binary.name }} updated EXE. Uploading here will update the
|
||||
binaries available for your "Build Site Agent" install package.
|
||||
</p>
|
||||
<p class="field-hint">
|
||||
Current staged version:
|
||||
<strong>{{ binary.current || 'none (legacy or unstaged)' }}</strong>
|
||||
<strong>{{ binary.current || 'none staged yet - upload a build below' }}</strong>
|
||||
</p>
|
||||
|
||||
<!-- Current release upload. The version is auto-detected from the
|
||||
EXE's PE version resource on select; the operator can override.
|
||||
This upload becomes the current staged build. -->
|
||||
<label class="field-label">
|
||||
Upload {{ binary.name }} binary current release
|
||||
</label>
|
||||
<div class="binary-upload">
|
||||
<input
|
||||
v-model="binary.version"
|
||||
class="form-control"
|
||||
type="text"
|
||||
placeholder="Version, e.g. 1.6.3"
|
||||
/>
|
||||
<input
|
||||
class="form-control"
|
||||
type="file"
|
||||
accept=".exe"
|
||||
@change="onBinaryFileChange(binary.key, $event)"
|
||||
/>
|
||||
<input
|
||||
v-model="binary.version"
|
||||
class="form-control"
|
||||
type="text"
|
||||
:placeholder="binary.detecting
|
||||
? 'Reading version...'
|
||||
: 'Version, auto-detected from EXE'"
|
||||
/>
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
type="button"
|
||||
:disabled="binary.busy || !binary.version || !binary.file"
|
||||
@click="uploadBinary(binary.key)"
|
||||
>
|
||||
{{ binary.busy ? 'Uploading...' : 'Upload' }}
|
||||
{{ binary.busy ? 'Uploading...' : 'Upload current release' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Rollback / legacy path. Stages a build into the version list
|
||||
without displacing the current release so it is available to
|
||||
roll back to. WARNING copy per intent: the version must be
|
||||
confirmed from the EXE properties before uploading. -->
|
||||
<label class="field-label">
|
||||
Upload legacy build for rollback, please confirm agent version
|
||||
</label>
|
||||
<p class="field-warning">
|
||||
WARNING: confirm agent version before uploading from the EXE
|
||||
properties and enter the version number.
|
||||
</p>
|
||||
<div class="binary-upload">
|
||||
<input
|
||||
class="form-control"
|
||||
type="file"
|
||||
accept=".exe"
|
||||
@change="onLegacyFileChange(binary.key, $event)"
|
||||
/>
|
||||
<input
|
||||
v-model="binary.legacyversion"
|
||||
class="form-control"
|
||||
type="text"
|
||||
placeholder="Version, e.g. 1.5.0"
|
||||
/>
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
type="button"
|
||||
:disabled="binary.busy || !binary.legacyversion || !binary.legacyfile"
|
||||
@click="uploadLegacy(binary.key)"
|
||||
>
|
||||
{{ binary.busy ? 'Uploading...' : 'Upload legacy build' }}
|
||||
</button>
|
||||
</div>
|
||||
<p v-if="binary.message" class="field-hint">{{ binary.message }}</p>
|
||||
<p v-if="binary.error" class="field-error">{{ binary.error }}</p>
|
||||
|
||||
<!-- Version selector: pick the staged build shipped by the next
|
||||
download. Ordered by version number (highest first). -->
|
||||
<div v-if="binary.versions.length" class="binary-upload">
|
||||
<label class="field-label" :for="`select-${binary.key}`">
|
||||
Active version
|
||||
</label>
|
||||
<select
|
||||
:id="`select-${binary.key}`"
|
||||
class="form-control"
|
||||
:value="binary.current || ''"
|
||||
:disabled="binary.busy"
|
||||
@change="setCurrentBinary(binary.key, $event.target.value)"
|
||||
>
|
||||
<option
|
||||
v-for="entry in binary.versions"
|
||||
:key="entry.version"
|
||||
:value="entry.version"
|
||||
>
|
||||
{{ entry.version }}{{ entry.iscurrent ? ' (current)' : '' }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div v-if="binary.versions.length" class="previous-versions">
|
||||
<button
|
||||
class="btn-link"
|
||||
type="button"
|
||||
@click="binary.showprevious = !binary.showprevious"
|
||||
>
|
||||
{{ binary.showprevious ? 'Hide' : 'Show' }} previous versions
|
||||
{{ binary.showprevious ? 'Hide' : 'Show' }} staged versions
|
||||
({{ binary.versions.length }})
|
||||
</button>
|
||||
<table v-if="binary.showprevious" class="versions-table">
|
||||
@@ -434,7 +502,7 @@ const copied = ref(false)
|
||||
const message = ref('')
|
||||
const error = ref('')
|
||||
|
||||
// Adoption tool (spike): build a one-shot, agentless enrollment download.
|
||||
// Adoption tool: build a one-shot, agentless enrollment download.
|
||||
const adoptbaseurl = ref('')
|
||||
const adoptcollectorkey = ref('')
|
||||
const adoptbusy = ref(false)
|
||||
@@ -458,11 +526,15 @@ const agenterror = ref('')
|
||||
// version list, and busy/message state so the two rows act independently. The
|
||||
// 'key' matches the backend binkey (agent | tray).
|
||||
const binaries = ref([
|
||||
{ key: 'agent', label: 'Endpoint agent (shopdbagent.exe)',
|
||||
current: null, versions: [], version: '', file: null,
|
||||
{ key: 'agent', label: 'ShopDB Agent (shopdbagent.exe)',
|
||||
name: 'ShopDB Agent',
|
||||
current: null, versions: [], version: '', file: '', detecting: false,
|
||||
legacyversion: '', legacyfile: '',
|
||||
busy: false, message: '', error: '', showprevious: false },
|
||||
{ key: 'tray', label: 'Tray agent (shopdb-endpoint-tray.exe)',
|
||||
current: null, versions: [], version: '', file: null,
|
||||
{ key: 'tray', label: 'Tray Agent (shopdb-endpoint-tray.exe)',
|
||||
name: 'Tray Agent',
|
||||
current: null, versions: [], version: '', file: '', detecting: false,
|
||||
legacyversion: '', legacyfile: '',
|
||||
busy: false, message: '', error: '', showprevious: false },
|
||||
])
|
||||
|
||||
@@ -664,11 +736,39 @@ async function buildSiteAgent() {
|
||||
}
|
||||
}
|
||||
|
||||
async function detectVersion(binkey, file) {
|
||||
const form = new FormData()
|
||||
form.append('file', file)
|
||||
const response = await api.post(
|
||||
`/endpoints/siteagent/binaries/${binkey}/detect`, form)
|
||||
return response.data.data?.version || ''
|
||||
}
|
||||
|
||||
function onBinaryFileChange(binkey, event) {
|
||||
const binary = binaryFor(binkey)
|
||||
if (!binary) return
|
||||
const files = event.target.files
|
||||
binary.file = files && files.length ? files[0] : null
|
||||
binary.file = files && files.length ? files[0] : ''
|
||||
binary.error = ''
|
||||
if (!binary.file) return
|
||||
binary.detecting = true
|
||||
detectVersion(binkey, binary.file)
|
||||
.then((version) => {
|
||||
if (version) binary.version = version
|
||||
})
|
||||
.catch((detectError) => {
|
||||
console.error(detectError)
|
||||
})
|
||||
.finally(() => {
|
||||
binary.detecting = false
|
||||
})
|
||||
}
|
||||
|
||||
function onLegacyFileChange(binkey, event) {
|
||||
const binary = binaryFor(binkey)
|
||||
if (!binary) return
|
||||
const files = event.target.files
|
||||
binary.legacyfile = files && files.length ? files[0] : ''
|
||||
}
|
||||
|
||||
async function uploadBinary(binkey) {
|
||||
@@ -686,7 +786,7 @@ async function uploadBinary(binkey) {
|
||||
const data = response.data.data || {}
|
||||
applyBinaryStatus(binkey, data.current, data.versions)
|
||||
binary.version = ''
|
||||
binary.file = null
|
||||
binary.file = ''
|
||||
binary.message = 'Uploaded and set as current.'
|
||||
} catch (uploadError) {
|
||||
binary.error = uploadError.response?.data?.data?.error?.message
|
||||
@@ -699,6 +799,35 @@ async function uploadBinary(binkey) {
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadLegacy(binkey) {
|
||||
const binary = binaryFor(binkey)
|
||||
if (!binary || !binary.legacyfile || !binary.legacyversion) return
|
||||
binary.busy = true
|
||||
binary.message = ''
|
||||
binary.error = ''
|
||||
try {
|
||||
const form = new FormData()
|
||||
form.append('version', binary.legacyversion)
|
||||
form.append('file', binary.legacyfile)
|
||||
form.append('makecurrent', 'false')
|
||||
const response = await api.post(
|
||||
`/endpoints/siteagent/binaries/${binkey}`, form)
|
||||
const data = response.data.data || {}
|
||||
applyBinaryStatus(binkey, data.current, data.versions)
|
||||
binary.legacyversion = ''
|
||||
binary.legacyfile = ''
|
||||
binary.message = 'Legacy build staged for rollback.'
|
||||
} catch (uploadError) {
|
||||
binary.error = uploadError.response?.data?.data?.error?.message
|
||||
|| (uploadError.response?.status === 403
|
||||
? 'You do not have permission to upload agent binaries'
|
||||
: 'Could not upload the legacy build')
|
||||
console.error(uploadError)
|
||||
} finally {
|
||||
binary.busy = false
|
||||
}
|
||||
}
|
||||
|
||||
async function setCurrentBinary(binkey, version) {
|
||||
const binary = binaryFor(binkey)
|
||||
if (!binary) return
|
||||
@@ -775,6 +904,14 @@ function editConfiguration() {
|
||||
}
|
||||
.binary-upload .form-control[type="text"] { max-width: 12rem; }
|
||||
.previous-versions { margin-top: 0.5rem; }
|
||||
.field-warning {
|
||||
margin: 0.25rem 0 0.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-left: 3px solid var(--color-warning, #b8860b);
|
||||
background: rgba(184, 134, 11, 0.08);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.btn-link {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
Reference in New Issue
Block a user