Show version tag in UI (#3743)
* Show version tag in UI * Add new arguments to test cloudbuild configuration * backend cloudbuild should use commit_sha as argument * Fix minor bug during dev
This commit is contained in:
parent
731aed4577
commit
e8356bc37a
|
|
@ -55,14 +55,16 @@ steps:
|
|||
waitFor: ["-"]
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args: ['build', '-t', 'gcr.io/$PROJECT_ID/frontend:$COMMIT_SHA',
|
||||
'--build-arg', 'COMMIT_HASH=$COMMIT_SHA', '-f',
|
||||
'/workspace/frontend/Dockerfile', '/workspace']
|
||||
'--build-arg', 'COMMIT_HASH=$COMMIT_SHA',
|
||||
'--build-arg', 'TAG_NAME=$TAG_NAME',
|
||||
'-f', '/workspace/frontend/Dockerfile', '/workspace']
|
||||
id: 'buildFrontend'
|
||||
waitFor: ['prepareFrontend']
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args: ['build', '-t', 'gcr.io/$PROJECT_ID/api-server:$COMMIT_SHA',
|
||||
'--build-arg', 'COMMIT_SHA=$COMMIT_SHA', '-f',
|
||||
'/workspace/backend/Dockerfile', '/workspace']
|
||||
'--build-arg', 'COMMIT_SHA=$COMMIT_SHA',
|
||||
'--build-arg', 'TAG_NAME=$TAG_NAME',
|
||||
'-f', '/workspace/backend/Dockerfile', '/workspace']
|
||||
id: 'buildApiServer'
|
||||
waitFor: ['copyPythonSDK']
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ FROM debian:stretch
|
|||
|
||||
ARG COMMIT_SHA=unknown
|
||||
ENV COMMIT_SHA=${COMMIT_SHA}
|
||||
ARG TAG_NAME=unknown
|
||||
ENV TAG_NAME=${TAG_NAME}
|
||||
|
||||
WORKDIR /bin
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ func startHttpProxy(resourceManager *resource.ResourceManager) {
|
|||
topMux.HandleFunc("/apis/v1beta1/pipelines/upload", pipelineUploadServer.UploadPipeline)
|
||||
topMux.HandleFunc("/apis/v1beta1/pipelines/upload_version", pipelineUploadServer.UploadPipelineVersion)
|
||||
topMux.HandleFunc("/apis/v1beta1/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, `{"commit_sha":"`+common.GetStringConfig("COMMIT_SHA")+`"}`)
|
||||
io.WriteString(w, `{"commit_sha":"`+common.GetStringConfigWithDefault("COMMIT_SHA", "unknown")+`", "tag_name":"`+common.GetStringConfigWithDefault("TAG_NAME", "unknown")+`"}`)
|
||||
})
|
||||
|
||||
topMux.Handle("/apis/", mux)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ FROM node:12.14.1 as build
|
|||
|
||||
ARG COMMIT_HASH
|
||||
ENV COMMIT_HASH=${COMMIT_HASH}
|
||||
ARG TAG_NAME
|
||||
ENV TAG_NAME=${TAG_NAME}
|
||||
|
||||
ARG DATE
|
||||
|
||||
|
|
@ -16,7 +18,8 @@ RUN npm run build
|
|||
|
||||
RUN mkdir -p ./server/dist && \
|
||||
echo ${COMMIT_HASH} > ./server/dist/COMMIT_HASH && \
|
||||
echo ${DATE} > ./server/dist/BUILD_DATE
|
||||
echo ${DATE} > ./server/dist/BUILD_DATE && \
|
||||
echo ${TAG_NAME} > ./server/dist/TAG_NAME
|
||||
|
||||
# Generate the dependency licenses files (one for the UI and one for the webserver),
|
||||
# concatenate them to one file under ./src/server
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
./BUILD_DATE
|
||||
./COMMIT_HASH
|
||||
BUILD_DATE
|
||||
COMMIT_HASH
|
||||
TAG_NAME
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
// 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.
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { PassThrough } from 'stream';
|
||||
import express from 'express';
|
||||
|
||||
|
|
@ -27,6 +24,7 @@ import { loadConfigs } from './configs';
|
|||
import * as minioHelper from './minio-helper';
|
||||
import { TEST_ONLY as K8S_TEST_EXPORT } from './k8s-helper';
|
||||
import { Server } from 'http';
|
||||
import { commonSetup } from './integration-tests/test-helper';
|
||||
|
||||
jest.mock('minio');
|
||||
jest.mock('node-fetch');
|
||||
|
|
@ -38,48 +36,17 @@ jest.mock('./minio-helper');
|
|||
|
||||
const mockedFetch: jest.Mock = fetch as any;
|
||||
|
||||
beforeEach(() => {
|
||||
const consoleInfoSpy = jest.spyOn(global.console, 'info');
|
||||
consoleInfoSpy.mockImplementation(() => null);
|
||||
const consoleLogSpy = jest.spyOn(global.console, 'log');
|
||||
consoleLogSpy.mockImplementation(() => null);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('UIServer apis', () => {
|
||||
let app: UIServer;
|
||||
const indexHtmlPath = path.resolve(os.tmpdir(), 'index.html');
|
||||
const argv = ['node', 'dist/server.js', os.tmpdir(), '3000'];
|
||||
const buildDate = new Date().toISOString();
|
||||
const tagName = '1.0.0';
|
||||
const commitHash = 'abcdefg';
|
||||
const indexHtmlContent = `
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
window.KFP_FLAGS.DEPLOYMENT=null
|
||||
</script>
|
||||
<script id="kubeflow-client-placeholder"></script>
|
||||
</head>
|
||||
</html>`;
|
||||
|
||||
beforeAll(() => {
|
||||
fs.writeFileSync(path.resolve(__dirname, 'BUILD_DATE'), buildDate);
|
||||
fs.writeFileSync(path.resolve(__dirname, 'COMMIT_HASH'), commitHash);
|
||||
fs.writeFileSync(indexHtmlPath, indexHtmlContent);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
fs.unlinkSync(path.resolve(__dirname, 'BUILD_DATE'));
|
||||
fs.unlinkSync(path.resolve(__dirname, 'COMMIT_HASH'));
|
||||
fs.unlinkSync(indexHtmlPath);
|
||||
});
|
||||
const { argv, buildDate, indexHtmlContent } = commonSetup({ tagName, commitHash });
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
const consoleInfoSpy = jest.spyOn(global.console, 'info');
|
||||
consoleInfoSpy.mockImplementation(() => null);
|
||||
const consoleLogSpy = jest.spyOn(global.console, 'log');
|
||||
consoleLogSpy.mockImplementation(() => null);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -157,6 +124,7 @@ describe('UIServer apis', () => {
|
|||
apiServerReady: false,
|
||||
buildDate,
|
||||
frontendCommitHash: commitHash,
|
||||
frontendTagName: tagName,
|
||||
},
|
||||
done,
|
||||
);
|
||||
|
|
@ -167,6 +135,7 @@ describe('UIServer apis', () => {
|
|||
json: () =>
|
||||
Promise.resolve({
|
||||
commit_sha: 'commit_sha',
|
||||
tag_name: '1.0.0',
|
||||
}),
|
||||
}));
|
||||
|
||||
|
|
@ -178,9 +147,11 @@ describe('UIServer apis', () => {
|
|||
200,
|
||||
{
|
||||
apiServerCommitHash: 'commit_sha',
|
||||
apiServerTagName: '1.0.0',
|
||||
apiServerReady: true,
|
||||
buildDate,
|
||||
frontendCommitHash: commitHash,
|
||||
frontendTagName: tagName,
|
||||
},
|
||||
done,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ import { Handler } from 'express';
|
|||
/** HealthzStats describes the ml-pipeline ui server state. */
|
||||
export interface HealthzStats {
|
||||
apiServerCommitHash: string;
|
||||
apiServerTagName: string;
|
||||
apiServerReady: boolean;
|
||||
buildDate: string;
|
||||
frontendCommitHash: string;
|
||||
frontendTagName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -41,15 +43,20 @@ export function getHealthzEndpoint(apiServerAddress: string, apiVersionPrefix: s
|
|||
export function getBuildMetadata(currentDir: string = path.resolve(__dirname)) {
|
||||
const buildDatePath = path.join(currentDir, 'BUILD_DATE');
|
||||
const commitHashPath = path.join(currentDir, 'COMMIT_HASH');
|
||||
const tagNamePath = path.join(currentDir, 'TAG_NAME');
|
||||
const buildDate = fs.existsSync(buildDatePath)
|
||||
? fs.readFileSync(buildDatePath, 'utf-8').trim()
|
||||
: '';
|
||||
const frontendCommitHash = fs.existsSync(commitHashPath)
|
||||
? fs.readFileSync(commitHashPath, 'utf-8').trim()
|
||||
: '';
|
||||
const frontendTagName = fs.existsSync(tagNamePath)
|
||||
? fs.readFileSync(tagNamePath, 'utf-8').trim()
|
||||
: '';
|
||||
return {
|
||||
buildDate,
|
||||
frontendCommitHash,
|
||||
frontendTagName,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +78,7 @@ export function getHealthzHandler(options: {
|
|||
healthzStats.apiServerReady = true;
|
||||
const serverStatus = await response.json();
|
||||
healthzStats.apiServerCommitHash = serverStatus.commit_sha;
|
||||
healthzStats.apiServerTagName = serverStatus.tag_name;
|
||||
} catch (e) {
|
||||
healthzStats.apiServerReady = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@ import * as path from 'path';
|
|||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
|
||||
export function commonSetup() {
|
||||
export function commonSetup(
|
||||
options: { commitHash?: string; tagName?: string } = {},
|
||||
): { argv: string[]; buildDate: string; indexHtmlPath: string; indexHtmlContent: string } {
|
||||
const indexHtmlPath = path.resolve(os.tmpdir(), 'index.html');
|
||||
const argv = ['node', 'dist/server.js', os.tmpdir(), '3000'];
|
||||
const buildDate = new Date().toISOString();
|
||||
const commitHash = 'abcdefg';
|
||||
const commitHash = options.commitHash || 'abcdefg';
|
||||
const tagName = options.tagName || '1.0.0';
|
||||
const indexHtmlContent = `
|
||||
<html>
|
||||
<head>
|
||||
|
|
@ -18,23 +21,19 @@ export function commonSetup() {
|
|||
</html>`;
|
||||
|
||||
beforeAll(() => {
|
||||
fs.writeFileSync(path.resolve(__dirname, 'BUILD_DATE'), buildDate);
|
||||
fs.writeFileSync(path.resolve(__dirname, 'COMMIT_HASH'), commitHash);
|
||||
console.log('beforeAll, writing files');
|
||||
fs.writeFileSync(path.resolve(__dirname, '..', 'BUILD_DATE'), buildDate);
|
||||
fs.writeFileSync(path.resolve(__dirname, '..', 'COMMIT_HASH'), commitHash);
|
||||
fs.writeFileSync(path.resolve(__dirname, '..', 'TAG_NAME'), tagName);
|
||||
fs.writeFileSync(indexHtmlPath, indexHtmlContent);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
fs.unlinkSync(path.resolve(__dirname, 'BUILD_DATE'));
|
||||
fs.unlinkSync(path.resolve(__dirname, 'COMMIT_HASH'));
|
||||
fs.unlinkSync(indexHtmlPath);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
return { argv };
|
||||
return { argv, buildDate, indexHtmlPath, indexHtmlContent };
|
||||
}
|
||||
|
||||
export function buildQuery(queriesMap: { [key: string]: string | undefined }): string {
|
||||
|
|
|
|||
|
|
@ -232,9 +232,11 @@ describe('SideNav', () => {
|
|||
it('populates the display build information using the response from the healthz endpoint', async () => {
|
||||
const buildInfo = {
|
||||
apiServerCommitHash: '0a7b9e38f2b9bcdef4bbf3234d971e1635b50cd5',
|
||||
apiServerTagName: '1.0.0',
|
||||
apiServerReady: true,
|
||||
buildDate: 'Tue Oct 23 14:23:53 UTC 2018',
|
||||
frontendCommitHash: '302e93ce99099173f387c7e0635476fe1b69ea98',
|
||||
frontendTagName: '1.0.0-rc1',
|
||||
};
|
||||
buildInfoSpy.mockImplementationOnce(() => buildInfo);
|
||||
|
||||
|
|
@ -243,6 +245,7 @@ describe('SideNav', () => {
|
|||
expect(tree).toMatchSnapshot();
|
||||
|
||||
expect(tree.state('displayBuildInfo')).toEqual({
|
||||
tagName: buildInfo.apiServerTagName,
|
||||
commitHash: buildInfo.apiServerCommitHash.substring(0, 7),
|
||||
commitUrl:
|
||||
'https://www.github.com/kubeflow/pipelines/commit/' + buildInfo.apiServerCommitHash,
|
||||
|
|
@ -306,12 +309,13 @@ describe('SideNav', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
it('displays the frontend commit hash if the api server hash is not returned', async () => {
|
||||
it('displays the frontend tag name if the api server hash is not returned', async () => {
|
||||
const buildInfo = {
|
||||
apiServerReady: true,
|
||||
// No apiServerCommitHash
|
||||
// No apiServerCommitHash or apiServerTagName
|
||||
buildDate: 'Tue Oct 23 14:23:53 UTC 2018',
|
||||
frontendCommitHash: '302e93ce99099173f387c7e0635476fe1b69ea98',
|
||||
frontendTagName: '1.0.0',
|
||||
};
|
||||
buildInfoSpy.mockImplementationOnce(() => buildInfo);
|
||||
|
||||
|
|
@ -321,6 +325,7 @@ describe('SideNav', () => {
|
|||
expect(tree.state('displayBuildInfo')).toEqual(
|
||||
expect.objectContaining({
|
||||
commitHash: buildInfo.frontendCommitHash.substring(0, 7),
|
||||
tagName: buildInfo.frontendTagName,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
|
@ -345,7 +350,7 @@ describe('SideNav', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("displays 'unknown' if the frontend and api server commit hashes are not returned", async () => {
|
||||
it("displays 'unknown' if the frontend and api server tag names/commit hashes are not returned", async () => {
|
||||
const buildInfo = {
|
||||
apiServerReady: true,
|
||||
// No apiServerCommitHash
|
||||
|
|
@ -360,6 +365,7 @@ describe('SideNav', () => {
|
|||
expect(tree.state('displayBuildInfo')).toEqual(
|
||||
expect.objectContaining({
|
||||
commitHash: 'unknown',
|
||||
tagName: 'unknown',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ interface DisplayBuildInfo {
|
|||
commitHash: string;
|
||||
commitUrl: string;
|
||||
date: string;
|
||||
tagName: string;
|
||||
}
|
||||
|
||||
interface SideNavProps extends RouterProps {
|
||||
|
|
@ -222,10 +223,13 @@ export class SideNav extends React.Component<SideNavInternalProps, SideNavState>
|
|||
async function fetchBuildInfo() {
|
||||
const buildInfo = await Apis.getBuildInfo();
|
||||
const commitHash = buildInfo.apiServerCommitHash || buildInfo.frontendCommitHash || '';
|
||||
const tagName = buildInfo.apiServerTagName || buildInfo.frontendTagName || '';
|
||||
return {
|
||||
tagName: tagName || 'unknown',
|
||||
commitHash: commitHash ? commitHash.substring(0, 7) : 'unknown',
|
||||
commitUrl:
|
||||
'https://www.github.com/kubeflow/pipelines' + (commitHash ? `/commit/${commitHash}` : ''),
|
||||
'https://www.github.com/kubeflow/pipelines' +
|
||||
(commitHash && commitHash !== 'unknown' ? `/commit/${commitHash}` : ''),
|
||||
date: buildInfo.buildDate
|
||||
? new Date(buildInfo.buildDate).toLocaleDateString('en-US')
|
||||
: 'unknown',
|
||||
|
|
@ -533,19 +537,19 @@ export class SideNav extends React.Component<SideNavInternalProps, SideNavState>
|
|||
)}
|
||||
{displayBuildInfo && (
|
||||
<Tooltip
|
||||
title={'Build date: ' + displayBuildInfo.date}
|
||||
title={`Build date: ${displayBuildInfo.date}, Commit hash: ${displayBuildInfo.commitHash}`}
|
||||
enterDelay={300}
|
||||
placement={'top-start'}
|
||||
>
|
||||
<div className={css.envMetadata}>
|
||||
<span>Build commit: </span>
|
||||
<span>Version: </span>
|
||||
<a
|
||||
href={displayBuildInfo.commitUrl}
|
||||
className={classes(css.link, commonCss.unstyled)}
|
||||
rel='noopener'
|
||||
target='_blank'
|
||||
>
|
||||
{displayBuildInfo.commitHash}
|
||||
{displayBuildInfo.tagName}
|
||||
</a>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -208,13 +208,13 @@ exports[`SideNav populates the display build information using the response from
|
|||
<WithStyles(Tooltip)
|
||||
enterDelay={300}
|
||||
placement="top-start"
|
||||
title="Build date: 10/23/2018"
|
||||
title="Build date: 10/23/2018, Commit hash: 0a7b9e3"
|
||||
>
|
||||
<div
|
||||
className="envMetadata"
|
||||
>
|
||||
<span>
|
||||
Build commit:
|
||||
Version:
|
||||
</span>
|
||||
<a
|
||||
className="link unstyled"
|
||||
|
|
@ -222,7 +222,7 @@ exports[`SideNav populates the display build information using the response from
|
|||
rel="noopener"
|
||||
target="_blank"
|
||||
>
|
||||
0a7b9e3
|
||||
1.0.0
|
||||
</a>
|
||||
</div>
|
||||
</WithStyles(Tooltip)>
|
||||
|
|
|
|||
|
|
@ -36,9 +36,11 @@ export interface ListRequest {
|
|||
|
||||
export interface BuildInfo {
|
||||
apiServerCommitHash?: string;
|
||||
apiServerTagName?: string;
|
||||
apiServerReady?: boolean;
|
||||
buildDate?: string;
|
||||
frontendCommitHash?: string;
|
||||
frontendTagName?: string;
|
||||
}
|
||||
|
||||
// Hack types from https://github.com/microsoft/TypeScript/issues/1897#issuecomment-557057387
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
steps:
|
||||
- id: "api-server"
|
||||
name: "gcr.io/cloud-builders/docker"
|
||||
args: [ 'build', '-t', '$_GCR_BASE/api-server', '-f', 'backend/Dockerfile', '.' ]
|
||||
args: ['build', '-t', '$_GCR_BASE/api-server', '-f', 'backend/Dockerfile', '--build-arg', 'COMMIT_SHA=abcdefg', '--build-arg', 'TAG_NAME=1.0-dev', '.']
|
||||
timeout: 1800s # 30min
|
||||
options:
|
||||
machineType: N1_HIGHCPU_8 # This is cpu intensive, use a better machine.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ steps:
|
|||
- id: "frontend"
|
||||
name: "gcr.io/cloud-builders/docker"
|
||||
args:
|
||||
["build", "-t", "$_GCR_BASE/frontend", "-f", "frontend/Dockerfile", "."]
|
||||
["build", "-t", "$_GCR_BASE/frontend", "-f", "frontend/Dockerfile", '--build-arg', 'COMMIT_HASH=abcdefg', '--build-arg', 'TAG_NAME=test', "."]
|
||||
waitFor: ["-"]
|
||||
- id: "viewer-crd-controller"
|
||||
name: "gcr.io/cloud-builders/docker"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ steps:
|
|||
- id: "frontend"
|
||||
name: "gcr.io/cloud-builders/docker"
|
||||
args:
|
||||
["build", "-t", "$_GCR_BASE/frontend", "-f", "frontend/Dockerfile", "."]
|
||||
["build", "-t", "$_GCR_BASE/frontend", "-f", "frontend/Dockerfile", '--build-arg', 'COMMIT_HASH=abcdefg', '--build-arg', 'TAG_NAME=1.0-dev', "."]
|
||||
images:
|
||||
- "$_GCR_BASE/frontend"
|
||||
timeout: 1800s # 30min
|
||||
|
|
|
|||
Loading…
Reference in New Issue