diff --git a/.editorconfig b/.editorconfig
index 9990ced8..ef71ea28 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,3 +5,7 @@ end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 100
+
+[{Dockerfile}]
+indent_style = space
+indent_size = 4
diff --git a/.github/workflows/checks.build.yaml b/.github/workflows/checks.build.yaml
index 47cfaa8c..312747ca 100644
--- a/.github/workflows/checks.build.yaml
+++ b/.github/workflows/checks.build.yaml
@@ -1,4 +1,4 @@
-name: build-checks
+name: checks.build
on:
push:
@@ -68,3 +68,33 @@ jobs:
-
name: Verify bundled desktop build artifacts
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
diff --git a/Dockerfile b/Dockerfile
index f617d791..0b451f51 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,13 +1,16 @@
# Build
-FROM node:lts-alpine as build-stage
+FROM node:lts-alpine AS build-stage
WORKDIR /app
-COPY package*.json ./
-RUN npm install
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
-FROM nginx:stable-alpine as production-stage
-COPY --from=build-stage /app/dist /usr/share/nginx/html
+FROM nginx:stable-alpine AS production-stage
+COPY --from=build-stage /dist /usr/share/nginx/html
EXPOSE 80
-CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/README.md b/README.md
index 4f7024c2..0a018859 100644
--- a/README.md
+++ b/README.md
@@ -66,8 +66,8 @@
diff --git a/docs/development.md b/docs/development.md
index eb00d72f..0709ccd1 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -60,6 +60,7 @@ See [ci-cd.md](./ci-cd.md) for more information.
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`
+3. Application should be available at [`http://localhost:8080`](http://localhost:8080)
### Building
@@ -81,11 +82,12 @@ See [ci-cd.md](./ci-cd.md) for more information.
#### Automation scripts
-- [**`node scripts/print-dist-dir.js [-- ]`**](../scripts/print-dist-dir.js):
+- [**`node scripts/print-dist-dir.js []`**](../scripts/print-dist-dir.js):
- 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 [-- ]`**](../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.
+- [**`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
diff --git a/scripts/verify-web-server-status.js b/scripts/verify-web-server-status.js
new file mode 100644
index 00000000..599b09a1
--- /dev/null
+++ b/scripts/verify-web-server-status.js
@@ -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();