From 53c92eba99e2f25024b88f9023f08f1362dd7b2e Mon Sep 17 00:00:00 2001 From: Just Jam Date: Fri, 18 Jul 2025 14:26:17 +0100 Subject: [PATCH] Add Docker version check and fix NCU --- config.schema.json | 8 ++++++- src/configTypes.ts | 1 + src/index.ts | 55 +++++++++++++++++++++++++++++++++++----------- src/ui-api.ts | 48 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 14 deletions(-) diff --git a/config.schema.json b/config.schema.json index 6744bbb..5495015 100644 --- a/config.schema.json +++ b/config.schema.json @@ -83,10 +83,16 @@ "description": "Check if updates are available for any installed plugins", "default": true }, + "checkDockerUpdates": { + "title": "Check for Docker image updates", + "type": "boolean", + "description": "Check if Docker image updates are available (only if running in Docker container)", + "default": true + }, "forceNcu": { "title": "Force npm-check-updates", "type": "boolean", - "description": "Force use of node-check-updates instead of homebridge-config-ui-x." + "description": "Force use of node-check-updates instead of homebridge-config-ui-x" } } } diff --git a/src/configTypes.ts b/src/configTypes.ts index 1ed2392..a008da0 100644 --- a/src/configTypes.ts +++ b/src/configTypes.ts @@ -7,4 +7,5 @@ export interface PluginUpdatePlatformConfig { checkHomebridge?: boolean checkHomebridgeUI?: boolean checkPlugins?: boolean + checkDockerUpdates?: boolean } diff --git a/src/index.ts b/src/index.ts index 6322e78..cad15f6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +/* eslint-disable antfu/if-newline */ + import type { API, Characteristic, @@ -24,6 +26,7 @@ import { PlatformAccessoryEvent, } from 'homebridge' +// eslint-disable-next-line ts/consistent-type-imports import { InstalledPlugin, UiApi } from './ui-api.js' let hap: HAP @@ -50,6 +53,7 @@ class PluginUpdatePlatform implements DynamicPlatformPlugin { private readonly checkHB: boolean private readonly checkHBUI: boolean private readonly checkPlugins: boolean + private readonly checkDocker: boolean private service?: Service private timer?: NodeJS.Timeout @@ -66,19 +70,20 @@ class PluginUpdatePlatform implements DynamicPlatformPlugin { this.isDocker = fs.existsSync('/homebridge/package.json') this.sensorInfo = this.getSensorInfo(this.config.sensorType) - this.checkHB = this.config.checkHomebridge ?? false; - this.checkHBUI = this.config.checkHomebridgeUI ?? false; - this.checkPlugins = this.config.checkPlugins ?? false; + this.checkHB = this.config.checkHomebridge ?? false + this.checkHBUI = this.config.checkHomebridgeUI ?? false + this.checkPlugins = this.config.checkPlugins ?? false + this.checkDocker = this.config.checkDockerUpdates ?? false api.on(APIEvent.DID_FINISH_LAUNCHING, this.addUpdateAccessory.bind(this)) } - async runNcu(args: Array): Promise { + async runNcu(args: Array, filter: string = '/^(@.*\\/)?homebridge(-.*)?$/'): Promise { args = [ path.resolve(__dirname, '../node_modules/npm-check-updates/build/src/bin/cli.js'), '--jsonUpgraded', '--filter', - '/^(@.*\\/)?homebridge(-.*)?$/', + filter, ].concat(args) const output = await new Promise((resolve, reject) => { @@ -110,23 +115,39 @@ class PluginUpdatePlatform implements DynamicPlatformPlugin { } async checkNcu(): Promise { - let results = await this.runNcu(['--global']) + const homebridgeFilter = 'homebridge' + const homebridgeUIFilter = 'homebridge-config-ui-x' + const pluginsFilter = '(?=(@.*\\/)?homebridge-)(?:(?!homebridge-config-ui-x).)*' + + const filters: string[] = [] + if (this.checkHB) filters.push(homebridgeFilter) + if (this.checkHBUI) filters.push(homebridgeUIFilter) + if (this.checkPlugins) filters.push(pluginsFilter) + + // eslint-disable-next-line prefer-template + const filter = '/^' + filters.join('|') + ')$/' + + let results = await this.runNcu(['--global'], filter) if (this.isDocker) { - const dockerResults = await this.runNcu(['--packageFile', '/homebridge/package.json']) - results = { ...results, ...dockerResults } + const dockerPackageResults = await this.runNcu(['--packageFile', '/homebridge/package.json'], filter) + results = { ...results, ...dockerPackageResults } + + const docker = await this.uiApi.getDocker() + if (docker.updateAvailable) { + results.push(docker) + } } const updates = Object.keys(results).length - this.log.debug(`npm-check-updates reports ${updates - } outdated package(s): ${JSON.stringify(results)}`) + this.log.debug(`npm-check-updates reports ${updates} available update(s): ${JSON.stringify(results)}`) return updates } async checkUi(): Promise { - let updatesAvailable: InstalledPlugin[] = [] - + const updatesAvailable: InstalledPlugin[] = [] + if (this.checkHB) { const homebridge = await this.uiApi.getHomebridge() @@ -152,7 +173,15 @@ class PluginUpdatePlatform implements DynamicPlatformPlugin { updatesAvailable.push(...plugins) } - this.log.debug(`homebridge-config-ui-x reports ${updatesAvailable.length} outdated package(s): ${JSON.stringify(updatesAvailable)}`) + if (this.isDocker && this.checkDocker) { + const docker = await this.uiApi.getDocker() + + if (docker.updateAvailable) { + updatesAvailable.push(docker) + } + } + + this.log.debug(`homebridge-config-ui-x reports ${updatesAvailable.length} available update(s): ${JSON.stringify(updatesAvailable)}`) return updatesAvailable.length } diff --git a/src/ui-api.ts b/src/ui-api.ts index f2a0b56..fbf5a11 100644 --- a/src/ui-api.ts +++ b/src/ui-api.ts @@ -37,6 +37,7 @@ export class UiApi { private readonly baseUrl?: string private readonly httpsAgent?: https.Agent private token?: string + private readonly dockerUrl?: string constructor(hbStoragePath: string) { const configPath = path.resolve(hbStoragePath, 'config.json') @@ -56,6 +57,11 @@ export class UiApi { this.baseUrl = `${protocol + host}:${port.toString()}` + const dockerProtocol = 'https://' + const dockerHost = 'hub.docker.com' + + this.dockerUrl = `${dockerProtocol + dockerHost}` + if (ssl) { this.httpsAgent = new https.Agent({ rejectUnauthorized: false }) // don't reject self-signed certs } @@ -87,6 +93,48 @@ export class UiApi { } } + public async getDocker(): Promise { + const currentDockerVersion = process.env.DOCKER_HOMEBRIDGE_VERSION + + let dockerInfo: InstalledPlugin = { + name: '', + installedVersion: '', + latestVersion: '', + updateAvailable: false, + } + + if (this.isConfigured() && currentDockerVersion !== undefined) { + const json = await this.makeDockerCall('/v2/repositories/homebridge/homebridge/tags/?page_size=10&page=1&ordering=last_updated') + const versions = JSON.parse(json).results as any[] + + const installedVersion = versions.filter(version => version.name === currentDockerVersion)[0] + const installedVersionDate = Date.parse(installedVersion.last_updated) + + const availableVersions = versions.filter(version => + !(version.name as string).includes('beta') && + (Date.parse(version.last_updated) > installedVersionDate) + ) + if (availableVersions.length > 0) { + dockerInfo = { + name: 'Docker image', + installedVersion: installedVersion, + latestVersion: availableVersions[0].name, + updateAvailable: true, + } + } + } + + return dockerInfo + } + + private async makeDockerCall(apiPath: string): Promise { + const response = await axios.get(this.dockerUrl + apiPath, { + httpsAgent: this.httpsAgent, + }) + + return response.data + } + private async makeCall(apiPath: string): Promise { const response = await axios.get(this.baseUrl + apiPath, { headers: { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy