Skip to content

Commit

Permalink
Webpack (stolostron#824)
Browse files Browse the repository at this point in the history
* initial webpack support

Signed-off-by: James Talton <[email protected]>

* webpack work

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* cleanup

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* cleanup

Signed-off-by: James Talton <[email protected]>

* work

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* fixes

Signed-off-by: James Talton <[email protected]>

* work

Signed-off-by: James Talton <[email protected]>

* work

Signed-off-by: James Talton <[email protected]>

* hot module replacement

Signed-off-by: James Talton <[email protected]>

* proxies

Signed-off-by: James Talton <[email protected]>

* types

Signed-off-by: James Talton <[email protected]>

* tsconfig

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* work

Signed-off-by: James Talton <[email protected]>

* hot reload fix

Signed-off-by: James Talton <[email protected]>

* update packages

Signed-off-by: James Talton <[email protected]>

* fixes

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* updates

Signed-off-by: James Talton <[email protected]>

* work

Signed-off-by: James Talton <[email protected]>

* webpack working

Signed-off-by: James Talton <[email protected]>

* fix output directory

Signed-off-by: James Talton <[email protected]>

* eslint fix

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* fix

Signed-off-by: James Talton <[email protected]>

* fixes

Signed-off-by: James Talton <[email protected]>

* fix file serve

Signed-off-by: James Talton <[email protected]>

* fix test

Signed-off-by: James Talton <[email protected]>

* fix production paths

Signed-off-by: James Talton <[email protected]>

* cleanup

Signed-off-by: James Talton <[email protected]>
  • Loading branch information
jamestalton authored Sep 1, 2021
1 parent d38a36f commit cb42e57
Show file tree
Hide file tree
Showing 196 changed files with 2,980 additions and 6,820 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
**/certs/
**/node_modules/
**/coverage/
**/lib/
**/dist/
**/build/
**/.eslintcache
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict = true
34 changes: 0 additions & 34 deletions @open-cluster-management/resources/package.json

This file was deleted.

8 changes: 0 additions & 8 deletions @open-cluster-management/resources/tsconfig.json

This file was deleted.

30 changes: 22 additions & 8 deletions Dockerfile.prow
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
# Copyright Contributors to the Open Cluster Management project

FROM registry.ci.openshift.org/open-cluster-management/builder:nodejs14-linux as builder
FROM registry.ci.openshift.org/open-cluster-management/builder:nodejs14-linux as packages
WORKDIR /app
COPY . .
COPY package.json yarn.lock ./
COPY ./backend/package.json /app/backend/package.json
COPY ./frontend/package.json /app/frontend/package.json

FROM packages as builder
RUN yarn install --frozen-lockfile --ignore-optional

FROM packages as production
RUN yarn install --production --frozen-lockfile --ignore-optional

FROM builder as backend
COPY ./backend ./backend
WORKDIR /app/backend
RUN yarn run build

FROM builder as frontend
COPY ./frontend ./frontend
WORKDIR /app/frontend
RUN yarn run build
RUN rm -rf node_modules && yarn install --frozen-lockfile --production --ignore-optional

FROM registry.access.redhat.com/ubi8/ubi-minimal
COPY --from=builder /usr/bin/node /usr/bin/node
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/backend/node_modules ./backend/node_modules
COPY --from=builder /app/backend/build ./backend
COPY --from=builder /app/frontend/build ./public
COPY --from=production /app/node_modules ./node_modules
COPY --from=production /app/backend/node_modules ./backend/node_modules
COPY --from=backend /app/backend/build ./backend
COPY --from=frontend /app/frontend/build ./public
USER 1001
CMD ["node", "backend/lib/main.js"]
25 changes: 15 additions & 10 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
"name": "@open-cluster-management/console-backend",
"version": "0.0.1",
"private": true,
"engines": {
"npm": "please-use-yarn",
"yarn": ">= 1.17.3",
"node": ">= 14"
},
"scripts": {
"watch": "yarn run start",
"watch": "echo",
"postinstall": "[ ! -d ./certs ] && yarn run generate-certs || true",
"build": "tsc --sourceMap false --declaration false",
"clean": "rm -rf coverage build",
Expand All @@ -28,21 +33,21 @@
"devDependencies": {
"@types/dotenv": "^8.2.0",
"@types/eslint": "^7.28.0",
"@types/jest": "^26.0.24",
"@types/node": "^16.4.3",
"@types/jest": "^27.0.0",
"@types/node": "^16.6.0",
"@types/node-fetch": "^2.5.12",
"@types/pino": "^6.3.10",
"@types/pino": "^6.3.11",
"@types/prettier": "^2.3.2",
"@types/raw-body": "^2.3.0",
"@typescript-eslint/eslint-plugin": "^4.28.5",
"@typescript-eslint/parser": "^4.28.5",
"eslint": "^7.31.0",
"jest": "^26.x.x",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/parser": "^4.29.1",
"eslint": "^7.32.0",
"jest": "^27.x.x",
"nock": "^13.1.1",
"pino-zen": "^1.0.20",
"prettier": "^2.3.2",
"ts-jest": "^26.x.x",
"ts-node": "^10.1.0",
"ts-jest": "^27.x.x",
"ts-node": "^10.2.0",
"ts-node-dev": "^1.1.8",
"typescript": "^4.3.5"
},
Expand Down
5 changes: 3 additions & 2 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ router.get(`/logout/`, logout)
router.get(`/events`, events)
router.post(`/proxy/search`, search)
router.get(`/authenticated`, authenticated)
router.get(`/*`, serve)
router.post(`/ansibletower`, ansibleTower)
router.get(`/*`, serve)

export async function requestHandler(req: Http2ServerRequest, res: Http2ServerResponse): Promise<void> {
if (process.env.NODE_ENV !== 'production') {
cors(req, res)
if (cors(req, res)) return
await delay(req, res)
}

Expand Down Expand Up @@ -76,6 +76,7 @@ export function start(): Promise<Http2Server | undefined> {
export async function stop(): Promise<void> {
if (process.env.NODE_ENV === 'development') {
setTimeout(() => {
logger.warn('process stop timeout. exiting...')
process.exit(1)
}, 0.5 * 1000).unref()
}
Expand Down
6 changes: 4 additions & 2 deletions backend/src/lib/cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { Http2ServerRequest, Http2ServerResponse } from 'http2'

export function cors(req: Http2ServerRequest, res: Http2ServerResponse): void {
export function cors(req: Http2ServerRequest, res: Http2ServerResponse): boolean {
if (process.env.NODE_ENV !== 'production') {
if (req.headers['origin']) {
res.setHeader('Access-Control-Allow-Origin', req.headers['origin'])
Expand All @@ -18,7 +18,9 @@ export function cors(req: Http2ServerRequest, res: Http2ServerResponse): void {
if (req.headers['access-control-request-headers']) {
res.setHeader('Access-Control-Allow-Headers', req.headers['access-control-request-headers'])
}
return res.writeHead(200).end()
res.writeHead(200).end()
return true
}
}
return false
}
5 changes: 3 additions & 2 deletions backend/src/lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ process.on('SIGTERM', () => {
})

process.on('uncaughtException', (err) => {
logger.error({ msg: `process uncaughtException`, error: err.message })
console.log(err.stack)
// console.error(err)
// logger.error({ msg: `process uncaughtException`, error: err.message })
// console.log(err.stack)
})

process.on('multipleResolves', (type, _promise, reason) => {
Expand Down
6 changes: 6 additions & 0 deletions backend/src/lib/request-retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ export function requestRetry(options: {
options.onResponse(response)
}
})
.on('error', (err) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
if ((err as any).code !== 'ABORT_ERR') {
throw err
}
})
.on('timeout', () => {
// Emitted when the underlying socket times out from inactivity.
// This only notifies that the socket has been idle.
Expand Down
80 changes: 57 additions & 23 deletions backend/src/routes/serve.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/* Copyright Contributors to the Open Cluster Management project */
import { createReadStream } from 'fs'
import { createReadStream, Stats } from 'fs'
import { stat } from 'fs/promises'
import { constants, Http2ServerRequest, Http2ServerResponse } from 'http2'
import { extname } from 'path'
import { pipeline } from 'stream'
import { parseCookies } from '../lib/cookies'
import { logger } from '../lib/logger'
import { redirect } from '../lib/respond'

const cacheControl = process.env.NODE_ENV === 'production' ? 'public, max-age=604800' : 'no-store'

export function serve(req: Http2ServerRequest, res: Http2ServerResponse): void {
export async function serve(req: Http2ServerRequest, res: Http2ServerResponse): Promise<void> {
try {
let url = req.url

Expand Down Expand Up @@ -41,15 +40,50 @@ export function serve(req: Http2ServerRequest, res: Http2ServerResponse): void {
logger.debug('unknown content type', `ext=${ext}`)
return res.writeHead(404).end()
}

const filePath = './public' + url
let stats: Stats
try {
stats = await stat(filePath)
} catch {
return res.writeHead(404).end()
}

if (/\bbr\b/.test(acceptEncoding)) {
try {
const brStats = await stat(filePath + '.br')
const readStream = createReadStream('./public' + url + '.br', { autoClose: true })
readStream
.on('open', () => {
res.writeHead(200, {
[constants.HTTP2_HEADER_CONTENT_ENCODING]: 'br',
[constants.HTTP2_HEADER_CONTENT_TYPE]: contentType,
[constants.HTTP2_HEADER_CONTENT_LENGTH]: brStats.size.toString(),
})
})
.on('error', (err) => {
// logger.error(err)
res.writeHead(404).end()
})
pipeline(readStream, res as unknown as NodeJS.WritableStream, (err) => {
// if (err) logger.error(err)
})
return
} catch {
// Do nothing
}
}

if (/\bgzip\b/.test(acceptEncoding)) {
try {
const gzStats = await stat(filePath + '.gz')
const readStream = createReadStream('./public' + url + '.gz', { autoClose: true })
readStream
.on('open', () => {
res.writeHead(200, {
[constants.HTTP2_HEADER_CONTENT_ENCODING]: 'gzip',
[constants.HTTP2_HEADER_CONTENT_TYPE]: contentType,
// [constants.HTTP2_HEADER_CONTENT_LENGTH]: stats.size.toString(),
[constants.HTTP2_HEADER_CONTENT_LENGTH]: gzStats.size.toString(),
})
})
.on('error', (err) => {
Expand All @@ -59,27 +93,27 @@ export function serve(req: Http2ServerRequest, res: Http2ServerResponse): void {
pipeline(readStream, res as unknown as NodeJS.WritableStream, (err) => {
// if (err) logger.error(err)
})
} catch (err) {
logger.error(err)
return res.writeHead(404).end()
return
} catch {
// Do nothing
}
} else {
const readStream = createReadStream('./public' + url, { autoClose: true })
readStream
.on('open', () => {
res.writeHead(200, {
[constants.HTTP2_HEADER_CONTENT_TYPE]: contentType,
})
})
.on('error', (err) => {
// logger.error(err)
res.writeHead(404).end()
}

const readStream = createReadStream('./public' + url, { autoClose: true })
readStream
.on('open', () => {
res.writeHead(200, {
[constants.HTTP2_HEADER_CONTENT_TYPE]: contentType,
[constants.HTTP2_HEADER_CONTENT_LENGTH]: stats.size.toString(),
})
pipeline(readStream, res as unknown as NodeJS.WritableStream, (err) => {
// if (err) logger.error(err)
})
}
return
.on('error', (err) => {
// logger.error(err)
res.writeHead(404).end()
})
pipeline(readStream, res as unknown as NodeJS.WritableStream, (err) => {
// if (err) logger.error(err)
})
} catch (err) {
logger.error(err)
return res.writeHead(404).end()
Expand Down
4 changes: 4 additions & 0 deletions frontend/babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// https://babeljs.io/docs/en/configuration
{
"presets": ["@babel/env", "@babel/react", "@babel/preset-typescript"]
}
12 changes: 10 additions & 2 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
automock: false,
rootDir: './src',
testResultsProcessor: 'jest-sonar-reporter',
setupFilesAfterEnv: ['<rootDir>/setupTests.ts'],
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/css.mock.js',
'\\.(css|less)$': '<rootDir>/css.mock.js',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/file.mock.js',
'\\.(css|less)$': 'identity-obj-proxy',
'monaco-editor': '<rootDir>/../../node_modules/react-monaco-editor',
},
watchPathIgnorePatterns: ['<rootDir>/../node_modules', '<rootDir>/../.eslintcache', '<rootDir>/../coverage'],
moduleFileExtensions: ['js', 'json', 'jsx', 'node', 'ts', 'tsx'],
transform: {
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.hbs$': 'jest-raw-loader',
'\\.(css|less)$': 'jest-raw-loader',
},
coverageReporters: ['text', 'text-summary', 'html', 'lcov'],
}
Loading

0 comments on commit cb42e57

Please sign in to comment.