Fix Docker build and improve checks #220
This commit improves multiple aspects of Docker builds:
- Enable artifact output validation for Dockerfile.
- Correct the path references in Dockerfile for the distribution
directory.
- Add Dockerfile specific indentation rules to `.editorconfig`.
- Use `npm run install-deps` for dependency installation, enhancing
build reliability.
- Add automation script `verify-web-server-status.js` to verify running
web server on given URL.
- Introduce automated build verification for Dockerfile:
- On macOS, install Docker with colima as the container runtime
because default agents do not include Docker and Docker runtime is
not installed due to licensing issues (see actions/runner-images#17).
- On Windows, there's no Linux container support (actions/runner#904,
actions/runner-images#1143), so keep the checks for macOS and Ubuntu
only.
This commit is contained in:
@@ -5,3 +5,7 @@ end_of_line = lf
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
max_line_length = 100
|
max_line_length = 100
|
||||||
|
|
||||||
|
[{Dockerfile}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|||||||
32
.github/workflows/checks.build.yaml
vendored
32
.github/workflows/checks.build.yaml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: build-checks
|
name: checks.build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -68,3 +68,33 @@ jobs:
|
|||||||
-
|
-
|
||||||
name: Verify bundled desktop build artifacts
|
name: Verify bundled desktop build artifacts
|
||||||
run: npm run check:verify-build-artifacts -- --electron-bundled
|
run: npm run check:verify-build-artifacts -- --electron-bundled
|
||||||
|
|
||||||
|
build-docker:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ macos, ubuntu ] # Windows runners do not support Linux containers
|
||||||
|
fail-fast: false # Allows to see results from other combinations
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Install Docker on macOS
|
||||||
|
if: matrix.os == 'macos' # macOS runner is missing Docker
|
||||||
|
run: |-
|
||||||
|
# Install Docker
|
||||||
|
brew install docker
|
||||||
|
# Docker on macOS misses daemon due to licensing, so install colima as runtime
|
||||||
|
brew install colima
|
||||||
|
# Start the daemon
|
||||||
|
colima start
|
||||||
|
-
|
||||||
|
name: Build Docker image
|
||||||
|
run: docker build -t undergroundwires/privacy.sexy:latest .
|
||||||
|
-
|
||||||
|
name: Run Docker image on port 8080
|
||||||
|
run: docker run -d -p 8080:80 --rm --name privacy.sexy undergroundwires/privacy.sexy:latest
|
||||||
|
-
|
||||||
|
name: Check server is up and returns HTTP 200
|
||||||
|
run: node ./scripts/verify-web-server-status.js --url http://localhost:8080
|
||||||
|
|||||||
17
Dockerfile
17
Dockerfile
@@ -1,13 +1,16 @@
|
|||||||
# Build
|
# Build
|
||||||
FROM node:lts-alpine as build-stage
|
FROM node:lts-alpine AS build-stage
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm install
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run build
|
RUN npm run install-deps
|
||||||
|
RUN npm run build \
|
||||||
|
&& npm run check:verify-build-artifacts -- --web
|
||||||
|
RUN mkdir /dist \
|
||||||
|
&& dist_directory=$(node 'scripts/print-dist-dir.js' --web) \
|
||||||
|
&& cp -a "${dist_directory}/." '/dist'
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM nginx:stable-alpine as production-stage
|
FROM nginx:stable-alpine AS production-stage
|
||||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
COPY --from=build-stage /dist /usr/share/nginx/html
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
@@ -66,8 +66,8 @@
|
|||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.build.yaml" target="_blank" rel="noopener noreferrer">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.build.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
alt="Build checks status"
|
alt="Status of build checks"
|
||||||
src="https://github.com/undergroundwires/privacy.sexy/workflows/build-checks/badge.svg"
|
src="https://github.com/undergroundwires/privacy.sexy/workflows/checks.build/badge.svg"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.desktop-runtime-errors.yaml" target="_blank" rel="noopener noreferrer">
|
<a href="https://github.com/undergroundwires/privacy.sexy/actions/workflows/checks.desktop-runtime-errors.yaml" target="_blank" rel="noopener noreferrer">
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ See [ci-cd.md](./ci-cd.md) for more information.
|
|||||||
|
|
||||||
1. Build: `docker build -t undergroundwires/privacy.sexy:latest .`
|
1. Build: `docker build -t undergroundwires/privacy.sexy:latest .`
|
||||||
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy undergroundwires/privacy.sexy:latest`
|
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy undergroundwires/privacy.sexy:latest`
|
||||||
|
3. Application should be available at [`http://localhost:8080`](http://localhost:8080)
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
@@ -81,11 +82,12 @@ See [ci-cd.md](./ci-cd.md) for more information.
|
|||||||
|
|
||||||
#### Automation scripts
|
#### Automation scripts
|
||||||
|
|
||||||
- [**`node scripts/print-dist-dir.js [-- <options>]`**](../scripts/print-dist-dir.js):
|
- [**`node scripts/print-dist-dir.js [<options>]`**](../scripts/print-dist-dir.js):
|
||||||
- Determines the absolute path of a distribution directory based on CLI arguments and outputs its absolute path.
|
- Determines the absolute path of a distribution directory based on CLI arguments and outputs its absolute path.
|
||||||
- Primarily used by automation scripts.
|
|
||||||
- [**`npm run check:verify-build-artifacts [-- <options>]`**](../scripts/verify-build-artifacts.js):
|
- [**`npm run check:verify-build-artifacts [-- <options>]`**](../scripts/verify-build-artifacts.js):
|
||||||
- Verifies the existence and content of build artifacts. Useful for ensuring that the build process is generating the expected output.
|
- Verifies the existence and content of build artifacts. Useful for ensuring that the build process is generating the expected output.
|
||||||
|
- [**`node scripts/verify-web-server-status.js --url [URL]`**](../scripts/verify-web-server-status.js):
|
||||||
|
- Checks if a specified server is up with retries and returns an HTTP 200 status code.
|
||||||
|
|
||||||
## Recommended extensions
|
## Recommended extensions
|
||||||
|
|
||||||
|
|||||||
62
scripts/verify-web-server-status.js
Normal file
62
scripts/verify-web-server-status.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Description:
|
||||||
|
* This script checks if a server, provided as a CLI argument, is up
|
||||||
|
* and returns an HTTP 200 status code.
|
||||||
|
* It is designed to provide easy verification of server availability
|
||||||
|
* and will retry a specified number of times.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node ./scripts/verify-web-server-status.js --url [URL]
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* --url URL of the server to check
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { get } from 'http';
|
||||||
|
|
||||||
|
const MAX_RETRIES = 30;
|
||||||
|
const RETRY_DELAY_IN_SECONDS = 3;
|
||||||
|
const URL_PARAMETER_NAME = '--url';
|
||||||
|
|
||||||
|
function checkServer(currentRetryCount = 1) {
|
||||||
|
const serverUrl = getServerUrl();
|
||||||
|
console.log(`Requesting ${serverUrl}...`);
|
||||||
|
get(serverUrl, (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
console.log('🎊 Success: The server is up and returned HTTP 200.');
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.log(`Server returned HTTP status code ${res.statusCode}.`);
|
||||||
|
retry(currentRetryCount);
|
||||||
|
}
|
||||||
|
}).on('error', (err) => {
|
||||||
|
console.error('Error making the request:', err);
|
||||||
|
retry(currentRetryCount);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function retry(currentRetryCount) {
|
||||||
|
console.log(`Attempt ${currentRetryCount}/${MAX_RETRIES}:`);
|
||||||
|
console.log(`Retrying in ${RETRY_DELAY_IN_SECONDS} seconds.`);
|
||||||
|
|
||||||
|
const remainingTime = (MAX_RETRIES - currentRetryCount) * RETRY_DELAY_IN_SECONDS;
|
||||||
|
console.log(`Time remaining before timeout: ${remainingTime}s`);
|
||||||
|
|
||||||
|
if (currentRetryCount < MAX_RETRIES) {
|
||||||
|
setTimeout(() => checkServer(currentRetryCount + 1), RETRY_DELAY_IN_SECONDS * 1000);
|
||||||
|
} else {
|
||||||
|
console.log('Failure: The server at did not return HTTP 200 within the allocated time. Exiting.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getServerUrl() {
|
||||||
|
const urlIndex = process.argv.indexOf(URL_PARAMETER_NAME);
|
||||||
|
if (urlIndex === -1 || urlIndex === process.argv.length - 1) {
|
||||||
|
console.error(`Parameter "${URL_PARAMETER_NAME}" is not provided.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
return process.argv[urlIndex + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
checkServer();
|
||||||
Reference in New Issue
Block a user