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 @@ Build checks status 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();