Add build_date to kbn:api/status (#157905)

## Summary

Adds build date to `GET kbn:api/status` similar to ES. Example output
running locally:

```json
{
  "name": "ES-DMVD5M3",
  "uuid": "545ba70c-063e-449b-af21-6c8e7b30f77e",
  "version": {
    "number": "8.9.0",
    "build_hash": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "build_number": 9007199254740991,
    "build_snapshot": false,
    "build_date": "2023-05-15T23:12:09.000Z"
  },
  ...rest
}
```


### Checklist

- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios


## Release Note

The status endpoint now returns the build date alongside other build
information.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Brad White 2023-05-25 10:21:47 -07:00 committed by GitHub
parent 97a93b34ee
commit 0c3ca366a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 96 additions and 6 deletions

View file

@ -187,6 +187,10 @@ Some features require special configuration when running in different modes (dev
|`12345`
|The build SHA (typically refers to the last commit's SHA)
|`buildDate`
|`2023-05-15T23:12:09+0000`
|The ISO 8601 date of the build
|===
To use any of the references listed above in a config validation schema, they can be accessed via `schema.contextRef('{CONTEXT_REFERENCE}')`:

View file

@ -17,7 +17,8 @@
"tsdocMetadata": "./build/tsdoc-metadata.json",
"build": {
"number": 8467,
"sha": "6cb7fec4e154faa0a4a3fee4b33dfef91b9870d9"
"sha": "6cb7fec4e154faa0a4a3fee4b33dfef91b9870d9",
"date": "2023-05-15T23:12:09+0000"
},
"homepage": "https://www.elastic.co/products/kibana",
"bugs": {

View file

@ -16,6 +16,7 @@ const buildServerVersion = (parts: Partial<ServerVersion> = {}): ServerVersion =
build_hash: 'build_hash',
build_number: 9000,
build_snapshot: false,
build_date: '2023-05-15T23:12:09.000Z',
...parts,
});

View file

@ -20,6 +20,7 @@ const mockedResponse: StatusResponse = {
build_hash: '9007199254740991',
build_number: 12,
build_snapshot: false,
build_date: '2023-05-15T23:12:09.000Z',
},
status: {
overall: {

View file

@ -21,6 +21,7 @@ const createPackageInfo = (parts: Partial<PackageInfo> = {}): PackageInfo => ({
dist: true,
branch: 'master',
version: '8.0.0',
buildDate: new Date('2023-05-15T23:12:09.000Z'),
});
const createUiPlugins = (...ids: string[]): UiPlugins => ({

View file

@ -25,6 +25,7 @@ function createCoreContext({ production = false }: { production?: boolean } = {}
buildNum: 100,
buildSha: 'buildSha',
dist: false,
buildDate: new Date('2023-05-15T23:12:09.000Z'),
},
},
};

View file

@ -6,16 +6,15 @@
* Side Public License, v 1.
*/
import { REPO_ROOT } from '@kbn/repo-info';
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest';
import { Env, IConfigService } from '@kbn/config';
import type { LoggerFactory } from '@kbn/logging';
import { loggerMock } from '@kbn/logging-mocks';
import { configServiceMock, getEnvOptions } from '@kbn/config-mocks';
import { configServiceMock, createTestEnv } from '@kbn/config-mocks';
import type { CoreContext } from '@kbn/core-base-server-internal';
function create({
env = Env.createDefault(REPO_ROOT, getEnvOptions()),
env = createTestEnv(),
logger = loggerMock.create(),
configService = configServiceMock.create(),
}: {

View file

@ -17,7 +17,6 @@
"@kbn/logging",
"@kbn/logging-mocks",
"@kbn/core-base-server-internal",
"@kbn/repo-info",
],
"exclude": [
"target/**/*",

View file

@ -24,6 +24,7 @@ export const createPluginInitializerContextMock = (config: unknown = {}) => {
buildNum: 100,
buildSha: 'buildSha',
dist: false,
buildDate: new Date('2023-05-15T23:12:09.000Z'),
},
},
logger: loggerMock.create(),

View file

@ -42,6 +42,7 @@ const createPluginInitializerContextMock = (config: unknown = {}) => {
buildNum: 100,
buildSha: 'buildSha',
dist: false,
buildDate: new Date('2023-05-15T23:12:09.000Z'),
},
},
logger: loggerMock.create(),

View file

@ -21,6 +21,7 @@ const packageInfo = {
buildSha: '',
version: '7.0.0-alpha1',
dist: false,
buildDate: new Date('2023-05-15T23:12:09.000Z'),
};
afterEach(() => {

View file

@ -19,6 +19,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -80,6 +81,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -145,6 +147,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -206,6 +209,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -267,6 +271,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -332,6 +337,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -393,6 +399,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -454,6 +461,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -519,6 +527,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -588,6 +597,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -649,6 +659,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -714,6 +725,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -783,6 +795,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,
@ -848,6 +861,7 @@ Object {
},
"packageInfo": Object {
"branch": Any<String>,
"buildDate": "2023-05-15T23:12:09.000Z",
"buildNum": Any<Number>,
"buildSha": Any<String>,
"dist": Any<Boolean>,

View file

@ -25,6 +25,7 @@ const createPackageInfo = (parts: Partial<PackageInfo> = {}): PackageInfo => ({
branch: 'master',
buildNum: 42,
buildSha: 'buildSha',
buildDate: new Date('2023-05-15T23:12:09.000Z'),
dist: false,
version: '8.0.0',
...parts,

View file

@ -27,6 +27,7 @@ import { InternalRenderingServicePreboot, InternalRenderingServiceSetup } from '
import { RenderingService } from './rendering_service';
import { AuthStatus } from '@kbn/core-http-server';
const BUILD_DATE = '2023-05-15T23:12:09+0000';
const INJECTED_METADATA = {
version: expect.any(String),
branch: expect.any(String),
@ -43,6 +44,7 @@ const INJECTED_METADATA = {
buildSha: expect.any(String),
dist: expect.any(Boolean),
version: expect.any(String),
buildDate: new Date(BUILD_DATE).toISOString(),
},
},
};
@ -387,6 +389,15 @@ function renderDarkModeTestCases(
describe('RenderingService', () => {
let service: RenderingService;
beforeAll(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date(BUILD_DATE));
});
afterAll(() => {
jest.useRealTimers();
});
beforeEach(() => {
jest.clearAllMocks();
service = new RenderingService(mockRenderingServiceParams);

View file

@ -34,6 +34,7 @@ export interface ServerVersion {
build_hash: string;
build_number: number;
build_snapshot: boolean;
build_date: string;
}
export interface StatusInfo {

View file

@ -88,7 +88,7 @@ export const registerStatusRoute = ({
},
},
async (context, req, res) => {
const { version, buildSha, buildNum } = config.packageInfo;
const { version, buildSha, buildNum, buildDate } = config.packageInfo;
const versionWithoutSnapshot = version.replace(SNAPSHOT_POSTFIX, '');
const [overall, coreOverall, core, plugins] = await firstValueFrom(combinedStatus$);
@ -121,6 +121,7 @@ export const registerStatusRoute = ({
build_hash: buildSha,
build_number: buildNum,
build_snapshot: SNAPSHOT_POSTFIX.test(version),
build_date: buildDate.toISOString(),
},
status: statusInfo,
metrics: {

View file

@ -45,6 +45,7 @@ export const createTestPackageInfo = ({ dist = true }: { dist?: boolean } = {}):
distributable: dist,
number: 123456789,
sha: 'XXXXXX',
date: '2023-05-15T23:12:09+0000',
},
};
};

View file

@ -28,6 +28,7 @@ Env {
},
"packageInfo": Object {
"branch": "feature-v1",
"buildDate": 2023-05-15T23:12:09.000Z,
"buildNum": 9007199254740991,
"buildSha": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"dist": false,
@ -69,6 +70,7 @@ Env {
},
"packageInfo": Object {
"branch": "feature-v1",
"buildDate": 2023-05-15T23:12:09.000Z,
"buildNum": 9007199254740991,
"buildSha": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"dist": false,
@ -109,6 +111,7 @@ Env {
},
"packageInfo": Object {
"branch": "some-branch",
"buildDate": 2023-05-15T23:12:09.000Z,
"buildNum": 9007199254740991,
"buildSha": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"dist": false,
@ -149,6 +152,7 @@ Env {
},
"packageInfo": Object {
"branch": "feature-v1",
"buildDate": 2023-05-15T23:12:09.000Z,
"buildNum": 100,
"buildSha": "feature-v1-build-sha",
"dist": true,
@ -189,6 +193,7 @@ Env {
},
"packageInfo": Object {
"branch": "feature-v1",
"buildDate": 2023-05-15T23:12:09.000Z,
"buildNum": 9007199254740991,
"buildSha": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"dist": false,
@ -229,6 +234,7 @@ Env {
},
"packageInfo": Object {
"branch": "feature-v1",
"buildDate": 2023-05-15T23:12:09.000Z,
"buildNum": 100,
"buildSha": "feature-v1-build-sha",
"dist": true,

View file

@ -31,6 +31,7 @@ const packageInfos: RawPackageInfo = {
build: {
number: 42,
sha: 'one',
date: '2023-05-15T23:12:09+0000',
},
};
const emptyArgv = getEnvOptions();
@ -238,6 +239,7 @@ test('correctly passes context', async () => {
distributable: true,
number: 100,
sha: 'feature-v1-build-sha',
date: '2023-05-15T23:12:09+0000',
},
};

View file

@ -13,6 +13,7 @@ import { Env, RawPackageInfo } from './env';
import { getEnvOptions } from './internal_mocks';
const REPO_ROOT = '/test/kibanaRoot';
const BUILD_DATE = '2023-05-15T23:12:09+0000';
const packageInfos: RawPackageInfo = {
branch: 'master',
@ -20,13 +21,23 @@ const packageInfos: RawPackageInfo = {
build: {
number: 42,
sha: 'one',
date: new Date(BUILD_DATE).toISOString(),
},
};
beforeAll(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date(BUILD_DATE));
});
beforeEach(() => {
mockPackage.raw = {};
});
afterAll(() => {
jest.useRealTimers();
});
test('correctly creates default environment in dev mode.', () => {
mockPackage.raw = {
branch: 'some-branch',
@ -51,6 +62,7 @@ test('correctly creates default environment in prod distributable mode.', () =>
distributable: true,
number: 100,
sha: 'feature-v1-build-sha',
date: BUILD_DATE,
},
};
@ -73,6 +85,7 @@ test('correctly creates default environment in prod non-distributable mode.', ()
distributable: false,
number: 100,
sha: 'feature-v1-build-sha',
date: BUILD_DATE,
},
};
@ -95,6 +108,7 @@ test('correctly creates default environment if `--env.name` is supplied.', () =>
distributable: false,
number: 100,
sha: 'feature-v1-build-sha',
date: BUILD_DATE,
},
};
@ -128,6 +142,7 @@ test('correctly creates environment with constructor.', () => {
distributable: true,
number: 100,
sha: 'feature-v1-build-sha',
date: BUILD_DATE,
},
},
getEnvOptions({

View file

@ -45,6 +45,7 @@ export interface RawPackageInfo {
distributable?: boolean;
number: number;
sha: string;
date: string;
};
}
@ -122,6 +123,7 @@ export class Env {
buildSha: isKibanaDistributable ? pkg.build.sha : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
version: pkg.version,
dist: isKibanaDistributable,
buildDate: isKibanaDistributable ? new Date(pkg.build.date) : new Date(),
});
}
}

View file

@ -14,6 +14,7 @@ export interface PackageInfo {
branch: string;
buildNum: number;
buildSha: string;
buildDate: Date;
dist: boolean;
}

View file

@ -14,6 +14,7 @@ export interface KibanaPackageJson {
number: number;
sha: string;
distributable?: boolean;
date: string;
};
dependencies: {
[dep: string]: string;

View file

@ -78,6 +78,7 @@ describe('GET /api/status', () => {
buildSha: 'xsha',
dist: true,
version: '9.9.9-SNAPSHOT',
buildDate: new Date('2023-05-15T23:12:09.000Z'),
},
serverName: 'xkibana',
uuid: 'xxxx-xxxxx',
@ -142,6 +143,7 @@ describe('GET /api/status', () => {
build_hash: 'xsha',
build_number: 1234,
build_snapshot: true,
build_date: new Date('2023-05-15T23:12:09.000Z').toISOString(),
});
const metricsMockValue = await firstValueFrom(metrics.getOpsMetrics$());
expect(result.body.metrics).toEqual({

View file

@ -99,6 +99,7 @@ function pluginInitializerContextMock<T>(config: T = {} as T) {
buildNum: 100,
buildSha: 'buildSha',
dist: false,
buildDate: new Date('2023-05-15T23:12:09.000Z'),
},
instanceUuid: 'instance-uuid',
configs: ['/some/path/to/config/kibana.yml'],

View file

@ -31,6 +31,7 @@ const config = new Config(
buildNumber: 1234,
buildSha: 'abcd1234',
buildVersion: '8.0.0',
buildDate: '2023-05-15T23:12:09+0000',
},
false,
false,

View file

@ -18,6 +18,7 @@ jest.mock('./version_info', () => ({
buildSha: 'abc1234',
buildVersion: '8.0.0',
buildNumber: 1234,
buildDate: '2023-05-15T23:12:09+0000',
}),
}));
@ -195,6 +196,13 @@ describe('#getBuildSha()', () => {
});
});
describe('#getBuildDate()', () => {
it('returns the date from the build info', async () => {
const config = await setup();
expect(config.getBuildDate()).toBe(versionInfo.buildDate);
});
});
describe('#isRelease()', () => {
it('returns true when marked as a release', async () => {
const config = await setup({ isRelease: true });

View file

@ -228,6 +228,13 @@ export class Config {
return this.versionInfo.buildSha;
}
/**
* Get the ISO 8601 date for this build
*/
getBuildDate() {
return this.versionInfo.buildDate;
}
/**
* Resolve a set of paths based from the target directory for this build.
*/

View file

@ -38,5 +38,6 @@ export async function getVersionInfo({ isRelease, versionQualifier, pkg }: Optio
buildSha,
buildVersion,
buildNumber: await getBuildNumber(),
buildDate: new Date().toISOString(),
};
}

View file

@ -35,6 +35,7 @@ const config = new Config(
buildNumber: 1234,
buildSha: 'abcd1234',
buildVersion: '8.0.0',
buildDate: '2023-05-15T23:12:09.000Z',
},
false,
false,

View file

@ -48,6 +48,7 @@ export const CreatePackageJson: Task = {
sha: config.getBuildSha(),
distributable: true,
release: config.isRelease,
date: config.getBuildDate(),
},
repository: pkg.repository,
engines: {

View file

@ -35,6 +35,7 @@ describe('PdfMaker', () => {
buildSha: 'screenshot-dfdfed0a',
dist: false,
version: '1000.0.0',
buildDate: new Date('2023-05-15T23:12:09.000Z'),
};
pdf = new PdfMaker(layout, undefined, packageInfo, logger);
});

View file

@ -57,6 +57,7 @@ describe('Screenshot Observable Pipeline', () => {
buildSha: 'screenshot-dfdfed0a',
dist: false,
version: '5000.0.0',
buildDate: new Date('2023-05-15T23:12:09.000Z'),
};
options = {
browserTimezone: 'UTC',