diff --git a/README.md b/README.md index ce52a07..64eb4f4 100644 --- a/README.md +++ b/README.md @@ -94,23 +94,31 @@ jobs: sokari/allure-docker-deploy:latest ``` +___ #### 2. Generate Allure results Add a step that outputs Allure result files to `/allure-results` path in the workflow. +___ + #### 3. Run the Workflow: Push your changes to the main branch and let GitHub Actions do the rest! +___ + #### 4. View Report information: Check the job summary in GitHub Actions for the report URL.
URL preview in GitHub Actions summary
+___ + #### 5. Get notified in Slack Add SLACK_TOKEN and SLACK_CHANNEL_ID as environment variable in the docker run command to receipt job completion notifications in Slack.
URL preview in GitHub Actions summary
+___ #### 6. View your test result files on the Firebase Developer console @@ -128,11 +136,15 @@ Tips 2. Configure `WEBSITE_EXPIRES` to manage the duration of hosted reports. 3. Mount `$GITHUB_STEP_SUMMARY` to display the test report URL in GitHub Actions job summaries. +___ + ### 2. For local test runs #### 1. Pull the Docker Image ```bash docker pull sokari/allure-docker-deploy:latest ``` +___ + #### 2. Run the Container ```shell docker run -d \ @@ -145,6 +157,8 @@ docker run -d \ -v /path/to/gcp-key.json:/credentials/key.json \ sokari/allure-docker-deploy ``` +___ + ##### 3. You can also use `docker-compose.yaml`: ```yaml services: @@ -164,11 +178,12 @@ services: WATCH_MODE: true TTL_SECS: 60 ``` +___ +#### 4. View test report URL in console +
Firebase CLI console output
-#### 4. Receive test report URL in console -
Firebase CLI console output
- +___ ## 🔑 **Key Features** * **Cloud Storage**: Automatically backs up test results to Google Cloud Storage. diff --git a/assets/clean-console-add.png b/assets/clean-console-add.png new file mode 100644 index 0000000..d618997 Binary files /dev/null and b/assets/clean-console-add.png differ diff --git a/start.sh b/start.sh index 235302d..8aaf48c 100644 --- a/start.sh +++ b/start.sh @@ -44,4 +44,4 @@ if [ -n "$TTL_SECS" ]; then fi fi echo 'Starting the app' -node /app/lib/index.js \ No newline at end of file +node --disable-warning=ExperimentalWarning /app/lib/index.js \ No newline at end of file diff --git a/worker/app/batch-processor.ts b/worker/app/batch-processor.ts index cf7d1e9..5324c53 100644 --- a/worker/app/batch-processor.ts +++ b/worker/app/batch-processor.ts @@ -71,8 +71,6 @@ export class BatchProcessor { // Process only up to `maxQueueSize` files in each batch const filesToProcess = this.fileQueue.splice(0, this.maxQueueSize); - console.log(`Processing ${filesToProcess.length} files...`); - try { const promises: Promise[] = []; if (websiteId) { diff --git a/worker/app/cloud-storage.ts b/worker/app/cloud-storage.ts index 20612a7..e0942d1 100644 --- a/worker/app/cloud-storage.ts +++ b/worker/app/cloud-storage.ts @@ -39,7 +39,7 @@ export class CloudStorage { destinationFilePath = path.basename(filePath); } try { - console.log(`Uploading ${destinationFilePath} to storage`) + // console.log(`Uploading ${destinationFilePath} to storage`) await CloudStorage.bucket.upload(filePath, { validation: !DEBUG, destination: `${storageHomeDir}/${destinationFilePath}`, @@ -58,7 +58,7 @@ export class CloudStorage { try { const [files] = await CloudStorage.bucket.getFiles({prefix: `${storageHomeDir}/`}); if (!files.length) { - console.log(`No files found in folder: ${storageHomeDir}/`); + console.log('No files to process from CloudStorage'); return; } await fs.mkdir(STAGING_PATH, {recursive: true}); // recursive, dont throw if exist @@ -69,10 +69,10 @@ export class CloudStorage { // Remove the preceding storageHomeDir path from the downloaded file const destination = path.join(STAGING_PATH, file.name.replace(`${storageHomeDir}/`, '')); await file.download({destination, validation: !DEBUG}); - console.log(`Downloaded ${file.name}`); })) } await Promise.all(downloadPromises); + console.log(`${files.length} files downloaded CloudStorage`); } catch (error) { console.error('Download error:', error); } diff --git a/worker/app/util.ts b/worker/app/util.ts index 8033cd3..a764962 100644 --- a/worker/app/util.ts +++ b/worker/app/util.ts @@ -2,15 +2,17 @@ import * as fsSync from 'fs' import * as fs from 'fs/promises' import * as path from "node:path"; import util from "node:util"; + const exec = util.promisify(require('child_process').exec) import {DEBUG, websiteId} from "../index"; import {StringBuilder} from "./string-builder"; import credential from "./credential"; - +import ansiEscapes from 'ansi-escapes'; +import chalk from "chalk"; export async function* getAllFilesStream(dir: string): AsyncGenerator { - const entries = await fs.readdir(dir, { withFileTypes: true }); + const entries = await fs.readdir(dir, {withFileTypes: true}); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { @@ -30,7 +32,7 @@ export async function* getAllFilesStream(dir: string): AsyncGenerator { export function validateWebsiteExpires(expires: string): boolean { const length = expires.length - if(length < 2 || length > 3){ + if (length < 2 || length > 3) { return false; } @@ -143,7 +145,9 @@ export async function publishToFireBaseHosting(configParentDir: string): Promise if (match && match[2]) { const url = match[2] - console.log(`Allure test report URL: ${url}`) + + console.log('Allure test report URL') + console.log(ansiEscapes.link(chalk.blue(url), url)); return url as string } else { console.warn('Could not parse URL from hosting.') diff --git a/worker/package-lock.json b/worker/package-lock.json index 1267107..e284df8 100644 --- a/worker/package-lock.json +++ b/worker/package-lock.json @@ -8,7 +8,9 @@ "dependencies": { "@slack/web-api": "^7.8.0", "allure-commandline": "^2.32.0", + "ansi-escapes": "^7.0.0", "async-mutex": "^0.5.0", + "chalk": "^5.3.0", "chokidar": "^4.0.1", "firebase-admin": "^13.0.1", "p-limit": "^6.1.0" @@ -160,6 +162,36 @@ "regexp-match-indices": "1.0.2" } }, + "node_modules/@cucumber/cucumber/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@cucumber/cucumber/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@cucumber/cucumber/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -1806,6 +1838,21 @@ "allure": "bin/allure" } }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2507,17 +2554,12 @@ } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -3030,6 +3072,18 @@ "once": "^1.4.0" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3455,6 +3509,23 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", diff --git a/worker/package.json b/worker/package.json index 898393f..1e52033 100644 --- a/worker/package.json +++ b/worker/package.json @@ -14,7 +14,9 @@ "dependencies": { "@slack/web-api": "^7.8.0", "allure-commandline": "^2.32.0", + "ansi-escapes": "^7.0.0", "async-mutex": "^0.5.0", + "chalk": "^5.3.0", "chokidar": "^4.0.1", "firebase-admin": "^13.0.1", "p-limit": "^6.1.0" diff --git a/worker/tsconfig.json b/worker/tsconfig.json index 1fe239d..8b65470 100644 --- a/worker/tsconfig.json +++ b/worker/tsconfig.json @@ -6,7 +6,7 @@ "outDir": "lib", "sourceMap": true, "strict": true, - "target": "es2017", + "target": "es2020", "allowSyntheticDefaultImports": true, "esModuleInterop": true },