From 5272b3467ea93b3fbfd83913132200847733225b Mon Sep 17 00:00:00 2001 From: Vinicius Fortuna Date: Wed, 31 Jan 2024 17:55:30 -0500 Subject: [PATCH] chore(server): inject version at build time (#1491) --- src/shadowbox/docker/Dockerfile | 6 ++--- src/shadowbox/docker/build.action.sh | 9 +++++++- src/shadowbox/package.json | 1 - src/shadowbox/server/main.ts | 4 ++-- src/shadowbox/server/manager_service.ts | 4 ++-- src/shadowbox/server/shared_metrics.spec.ts | 6 ++--- src/shadowbox/server/shared_metrics.ts | 4 ++-- src/shadowbox/server/version.ts | 25 +++++++++++++++++++++ src/shadowbox/webpack.config.js | 2 ++ 9 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 src/shadowbox/server/version.ts diff --git a/src/shadowbox/docker/Dockerfile b/src/shadowbox/docker/Dockerfile index 850f3bf3d..f6075ab78 100644 --- a/src/shadowbox/docker/Dockerfile +++ b/src/shadowbox/docker/Dockerfile @@ -34,8 +34,9 @@ COPY tsconfig.json ./ COPY third_party third_party ARG ARCH +ARG VERSION -RUN ARCH=${ARCH} ROOT_DIR=/ npm run action shadowbox/server/build +RUN ARCH=${ARCH} ROOT_DIR=/ SB_VERSION=${VERSION} npm run action shadowbox/server/build # shadowbox image FROM ${NODE_IMAGE} @@ -43,8 +44,7 @@ FROM ${NODE_IMAGE} # Save metadata on the software versions we are using. LABEL shadowbox.node_version=16.18.0 -ARG GITHUB_RELEASE -LABEL shadowbox.github.release="${GITHUB_RELEASE}" +LABEL shadowbox.github.release=${VERSION} # The user management service doesn't quit with SIGTERM. STOPSIGNAL SIGKILL diff --git a/src/shadowbox/docker/build.action.sh b/src/shadowbox/docker/build.action.sh index bbf2dd919..f24a31cf1 100755 --- a/src/shadowbox/docker/build.action.sh +++ b/src/shadowbox/docker/build.action.sh @@ -14,6 +14,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Environment inputs: +# - SB_VERSION +# - SB_IMAGE +# - ARCH +# - NODE_IMAGE +# - ROOT_DIR + export DOCKER_CONTENT_TRUST="${DOCKER_CONTENT_TRUST:-1}" # Enable Docker BuildKit (https://docs.docker.com/develop/develop-images/build_enhancements) export DOCKER_BUILDKIT=1 @@ -38,7 +45,7 @@ readonly NODE_IMAGE=$( docker build --force-rm \ --build-arg ARCH="${ARCH}" \ --build-arg NODE_IMAGE="${NODE_IMAGE}" \ - --build-arg GITHUB_RELEASE="${TRAVIS_TAG:-none}" \ + --build-arg VERSION="${SB_VERSION:-dev}" \ -f src/shadowbox/docker/Dockerfile \ -t "${SB_IMAGE:-localhost/outline/shadowbox}" \ "${ROOT_DIR}" diff --git a/src/shadowbox/package.json b/src/shadowbox/package.json index a2c952cbc..89a2ef5d5 100644 --- a/src/shadowbox/package.json +++ b/src/shadowbox/package.json @@ -1,7 +1,6 @@ { "name": "outline-server", "private": true, - "version": "1.7.2", "description": "Outline server", "main": "build/server/main.js", "author": "Outline", diff --git a/src/shadowbox/server/main.ts b/src/shadowbox/server/main.ts index 98c92440b..ba938eb7a 100644 --- a/src/shadowbox/server/main.ts +++ b/src/shadowbox/server/main.ts @@ -27,7 +27,7 @@ import * as logging from '../infrastructure/logging'; import {PrometheusClient, startPrometheus} from '../infrastructure/prometheus_scraper'; import {RolloutTracker} from '../infrastructure/rollout'; import {AccessKeyId} from '../model/access_key'; -import {version} from '../package.json'; +import * as version from './version'; import {PrometheusManagerMetrics} from './manager_metrics'; import {bindService, ShadowsocksManagerService} from './manager_service'; @@ -82,7 +82,7 @@ function createRolloutTracker( async function main() { const verbose = process.env.LOG_LEVEL === 'debug'; logging.info('======== Outline Server main() ========'); - logging.info(`Version is ${version}`); + logging.info(`Version is ${version.getPackageVersion()}`); const portProvider = new PortProvider(); const accessKeyConfig = json_config.loadFileConfig( diff --git a/src/shadowbox/server/manager_service.ts b/src/shadowbox/server/manager_service.ts index 45fa905bd..91ae444fe 100644 --- a/src/shadowbox/server/manager_service.ts +++ b/src/shadowbox/server/manager_service.ts @@ -22,7 +22,7 @@ import {JsonConfig} from '../infrastructure/json_config'; import * as logging from '../infrastructure/logging'; import {AccessKey, AccessKeyRepository, DataLimit} from '../model/access_key'; import * as errors from '../model/errors'; -import {version} from '../package.json'; +import * as version from './version'; import {ManagerMetrics} from './manager_metrics'; import {ServerConfigJson} from './server_config'; @@ -258,7 +258,7 @@ export class ShadowsocksManagerService { serverId: this.serverConfig.data().serverId, metricsEnabled: this.serverConfig.data().metricsEnabled || false, createdTimestampMs: this.serverConfig.data().createdTimestampMs, - version, + version: version.getPackageVersion(), accessKeyDataLimit: this.serverConfig.data().accessKeyDataLimit, portForNewAccessKeys: this.serverConfig.data().portForNewAccessKeys, hostnameForAccessKeys: this.serverConfig.data().hostname, diff --git a/src/shadowbox/server/shared_metrics.spec.ts b/src/shadowbox/server/shared_metrics.spec.ts index 2038d885e..c13460b0b 100644 --- a/src/shadowbox/server/shared_metrics.spec.ts +++ b/src/shadowbox/server/shared_metrics.spec.ts @@ -15,7 +15,7 @@ import {ManualClock} from '../infrastructure/clock'; import {InMemoryConfig} from '../infrastructure/json_config'; import {AccessKeyId, DataLimit} from '../model/access_key'; -import {version} from '../package.json'; +import * as version from './version'; import {AccessKeyConfigJson} from './server_access_key'; import {ServerConfigJson} from './server_config'; @@ -224,7 +224,7 @@ describe('OutlineSharedMetricsPublisher', () => { await clock.runCallbacks(); expect(metricsCollector.collectedFeatureMetricsReport).toEqual({ serverId: 'server-id', - serverVersion: version, + serverVersion: version.getPackageVersion(), timestampUtcMs: timestamp, dataLimit: { enabled: true, @@ -238,7 +238,7 @@ describe('OutlineSharedMetricsPublisher', () => { await clock.runCallbacks(); expect(metricsCollector.collectedFeatureMetricsReport).toEqual({ serverId: 'server-id', - serverVersion: version, + serverVersion: version.getPackageVersion(), timestampUtcMs: timestamp, dataLimit: { enabled: false, diff --git a/src/shadowbox/server/shared_metrics.ts b/src/shadowbox/server/shared_metrics.ts index e96a0792f..3354902d7 100644 --- a/src/shadowbox/server/shared_metrics.ts +++ b/src/shadowbox/server/shared_metrics.ts @@ -18,7 +18,7 @@ import {JsonConfig} from '../infrastructure/json_config'; import * as logging from '../infrastructure/logging'; import {PrometheusClient} from '../infrastructure/prometheus_scraper'; import {AccessKeyId, AccessKeyMetricsId} from '../model/access_key'; -import {version} from '../package.json'; +import * as version from './version'; import {AccessKeyConfigJson} from './server_access_key'; import {ServerConfigJson} from './server_config'; @@ -280,7 +280,7 @@ export class OutlineSharedMetricsPublisher implements SharedMetricsPublisher { const keys = this.keyConfig.data().accessKeys; const featureMetricsReport = { serverId: this.serverConfig.data().serverId, - serverVersion: version, + serverVersion: version.getPackageVersion(), timestampUtcMs: this.clock.now(), dataLimit: { enabled: !!this.serverConfig.data().accessKeyDataLimit, diff --git a/src/shadowbox/server/version.ts b/src/shadowbox/server/version.ts new file mode 100644 index 000000000..970c6227b --- /dev/null +++ b/src/shadowbox/server/version.ts @@ -0,0 +1,25 @@ +// Copyright 2024 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Injected by WebPack with webpack.DefinePlugin. +declare const __VERSION__: string; + +export function getPackageVersion(): string { + try { + return __VERSION__; + } catch { + // Catch the ReferenceError if __VERSION__ is not injected. + return "dev" + } +} diff --git a/src/shadowbox/webpack.config.js b/src/shadowbox/webpack.config.js index dd1d9cbb3..10eaeedd1 100644 --- a/src/shadowbox/webpack.config.js +++ b/src/shadowbox/webpack.config.js @@ -30,6 +30,8 @@ const config = { __dirname: false, }, plugins: [ + // Used by server/version.ts. + process.env.SB_VERSION ? new webpack.DefinePlugin({'__VERSION__': JSON.stringify(process.env.SB_VERSION)}): undefined, // WORKAROUND: some of our (transitive) dependencies use node-gently, which hijacks `require`. // Setting global.GENTLY to false makes these dependencies use standard require. new webpack.DefinePlugin({'global.GENTLY': false}),