diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index efff3acf8..50b68c5d8 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -456,7 +456,7 @@ jobs: runs-on: self-hosted strategy: matrix: - node-version: [18] + node-version: [16] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - name: Checkout repository diff --git a/.github/workflows/trivir.yml b/.github/workflows/trivir.yml new file mode 100644 index 000000000..67c491307 --- /dev/null +++ b/.github/workflows/trivir.yml @@ -0,0 +1,458 @@ +name: 'Frodo CLI Release Pipeline' + +on: + push: + branches: + - trivir + pull_request: + branches: + - trivir + workflow_dispatch: + +env: + NODE_VERSION: 18 + +jobs: + build: + name: 'Build' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: TriVir changes + run: | + npm run trivir-frodo-lib + npm ci + + - name: 'Prepare Version Bump' + id: version-bump + uses: 'phips28/gh-action-bump-version@master' + with: + version-type: 'prerelease' + major-wording: 'MAJOR RELEASE' + minor-wording: 'MINOR RELEASE' + patch-wording: 'PATCH RELEASE' + rc-wording: '' + tag-prefix: 'v' + default: prerelease + preid: 'trivir' + bump-policy: 'ignore' + skip-commit: 'true' + skip-tag: 'true' + skip-push: 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: 'Version From Tag' + id: version-from-tag + run: echo "version=$(echo '${{ steps.version-bump.outputs.newTag }}' | sed 's/v//')" >> "$GITHUB_OUTPUT" + + - name: Build frodo-cli esm + run: npm run transpile-esm + + - name: Build frodo-cli cjs + run: npm run transpile-cjs + + - name: Lint + run: npm run lint + + - name: Type Check + run: npx tsc + + - name: Security Audit + run: npm audit --omit=dev + + - uses: actions/upload-artifact@v3 + with: + name: build + path: | + package.json + package-lock.json + esm + cjs + + outputs: + newTag: ${{ steps.version-bump.outputs.newTag }} + newVersion: ${{ steps.version-from-tag.outputs.version }} + preRelease: ${{ contains(steps.version-bump.outputs.newTag, '-') }} + + smoke-tests: + name: 'Smoke Tests' + needs: build + # You must use a Linux environment when using service containers or container jobs + runs-on: ubuntu-latest +# strategy: +# matrix: +# node-version: [20, 18, 16, 14] +# # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ +# +# # Service containers to run with `smoke-tests` +# services: +# # Label used to access the service container +# squid: +# # Docker Hub image +# image: ubuntu/squid +# # +# ports: +# # Maps tcp port 3128 on the host to the same port in the service container +# - 3128:3128 +# + steps: + - name: Checkout repository + uses: actions/checkout@v3 +# +# - name: Use Node.js ${{ matrix.node-version }} +# uses: actions/setup-node@v3 +# with: +# # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ +# node-version: ${{ matrix.node-version }} +# cache: 'npm' +# +# # Update npm for older node versions to avoid errors with npm ci due to newer package-lock.json format +# # TODO: conditionally update npm when it is older than the required version +# - name: Update npm +# run: npm install -g npm +# +# - uses: actions/download-artifact@v3 +# with: +# name: build +# +# - name: Install dependencies +# run: npm ci +# +# - name: Install frodo-cli globally +# run: npm i -g +# +# - name: CLI Help Tests +# run: npm test +# +# - name: Version Test +# run: frodo -v +# +# - name: Direct Tests +# env: +# FIDC_TENANT_URL: ${{ secrets.FIDC_TENANT_URL }} +# FIDC_TENANT_ADMIN_USERNAME: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }} +# FIDC_TENANT_ADMIN_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }} +# run: | +# frodo conn add "$FIDC_TENANT_URL" "$FIDC_TENANT_ADMIN_USERNAME" "$FIDC_TENANT_ADMIN_PASSWORD" +# frodo info "$FIDC_TENANT_URL" +# +# - name: Proxy Tests +# env: +# HTTPS_PROXY: 'http://127.0.0.1:3128' +# FIDC_TENANT_URL: ${{ secrets.FIDC_TENANT_URL }} +# FIDC_TENANT_ADMIN_USERNAME: ${{ secrets.FIDC_TENANT_ADMIN_USERNAME }} +# FIDC_TENANT_ADMIN_PASSWORD: ${{ secrets.FIDC_TENANT_ADMIN_PASSWORD }} +# run: | +# frodo conn add "$FIDC_TENANT_URL" "$FIDC_TENANT_ADMIN_USERNAME" "$FIDC_TENANT_ADMIN_PASSWORD" +# frodo info "$FIDC_TENANT_URL" + + release: + if: github.event_name != 'pull_request' +# needs: [build, linux-binary-release, linux-arm64-binary-release, macos-binary-release, npm-release, windows-binary-release] + needs: [build, linux-binary-release, macos-binary-release, npm-release, windows-binary-release] + name: 'Release' + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - uses: actions/download-artifact@v3 + with: + name: build + + - uses: actions/download-artifact@v3 + with: + name: dist + + - name: 'Github SHA' + id: github-sha + run: echo ${{ github.sha }} > Release.txt + + - name: Update Changelog + uses: thomaseizinger/keep-a-changelog-new-release@1.3.0 + with: + tag: ${{ needs.build.outputs.newTag }} + + - name: 'Output Changelog' + run: cat CHANGELOG.md + + - name: 'Release Header' + id: release-header + run: echo "header=$(echo `grep '## \\[${{ needs.build.outputs.newVersion }}] -' CHANGELOG.md | sed 's/## //' | sed 's/\\[//' | sed 's/]//'`)" >> "$GITHUB_OUTPUT" + + - name: 'Extract Release Notes' + id: extract-release-notes + uses: 'dahlia/submark@main' + with: + input-file: 'CHANGELOG.md' + heading-level: 2 + heading-title-text: '${{ steps.release-header.outputs.header }}' + ignore-case: true + omit-heading: true + + - name: Commit updated changelog and version + id: commit-changelog + #TODO: Figure out what values we should use for user.name and user.email + run: | + git config user.name "Automated Version Bump" + git config user.email "gh-action-bump-version@users.noreply.github.com" + git add CHANGELOG.md package.json + git commit --message "Updated changelog and version for release ${{ needs.build.outputs.newTag }}" + git push + + - name: Release + uses: softprops/action-gh-release@v1 + with: + name: Frodo CLI ${{ needs.build.outputs.newVersion }} + tag_name: ${{ needs.build.outputs.newTag }} + body: ${{ steps.extract-release-notes.outputs.output-text }} + prerelease: ${{ needs.build.outputs.preRelease }} + generate_release_notes: ${{ contains(needs.build.outputs.newTag, '-') }} + files: | + CHANGELOG.md + LICENSE + Release.txt + frodo-linux-${{ needs.build.outputs.newVersion }}.zip + frodo-macos-${{ needs.build.outputs.newVersion }}.zip + frodo-win-${{ needs.build.outputs.newVersion }}.zip +# frodo-linux-arm64-${{ needs.build.outputs.newVersion }}.zip + token: ${{ secrets.GITHUB_TOKEN }} + + npm-release: + if: false + # if: github.event_name != 'pull_request' + # npm-release only needs the build job but since it is inconvenient to unpublish an npm we want this job to run last + # needs: [build, linux-binary-release, linux-arm64-binary-release, macos-binary-release, windows-binary-release] + needs: [build, linux-binary-release, macos-binary-release, windows-binary-release] + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - uses: actions/download-artifact@v3 + with: + name: build + + - name: Install dependencies + run: npm ci + + - name: Pre-Release + if: ${{ fromJSON(needs.build.outputs.preRelease) }} + uses: JS-DevTools/npm-publish@v1 + with: + access: public + tag: 'next' + token: ${{ secrets.NPM_ACCESS_TOKEN }} + + - name: Release + if: ${{ ! fromJSON(needs.build.outputs.preRelease) }} + uses: JS-DevTools/npm-publish@v1 + with: + access: public + token: ${{ secrets.NPM_ACCESS_TOKEN }} + + - name: Add next tag + if: ${{ ! fromJSON(needs.build.outputs.preRelease) }} + run: | + export INPUT_TOKEN=${{ secrets.NPM_ACCESS_TOKEN }} + npm whoami + npm dist-tag add @trivir/frodo-cli@${{ needs.build.outputs.newVersion }} next + + macos-binary-release: + needs: [build, smoke-tests] + runs-on: macos-latest + timeout-minutes: 15 + steps: + - name: Install the Apple certificate + env: + DEVELOPMENT_CERTIFICATE_DATA: ${{ secrets.DEVELOPMENT_CERTIFICATE_DATA }} + DEVELOPMENT_CERTIFICATE_PASSPHRASE: ${{ secrets.DEVELOPMENT_CERTIFICATE_PASSPHRASE }} + INTERMEDIATE_CERTIFICATE_DATA: ${{ secrets.INTERMEDIATE_CERTIFICATE_DATA }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + # create variables + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + INTERMEDIATE_CERTIFICATE_PATH=$RUNNER_TEMP/intermediate_certificate.p12 + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + # import certificates from secrets + echo -n "$DEVELOPMENT_CERTIFICATE_DATA" | base64 --decode --output $CERTIFICATE_PATH + echo -n "$INTERMEDIATE_CERTIFICATE_DATA" | base64 --decode --output $INTERMEDIATE_CERTIFICATE_PATH + + # create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import certificate to keychain + security import $CERTIFICATE_PATH -P "$DEVELOPMENT_CERTIFICATE_PASSPHRASE" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + #security import $INTERMEDIATE_CERTIFICATE_PATH -P "$DEVELOPMENT_CERTIFICATE_PASSPHRASE" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + + - uses: actions/download-artifact@v3 + with: + name: build + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run dist-pkg + + # + # Fail early on failing tests. + # + - name: 'Test' + run: | + ./frodo -v + ./frodo journey -h + ./frodo journey export -h + + # + # Re-sign the application with the "Developer ID" certificate. + # + - name: Sign distribution binary + # working-directory: ./dist/bin + run: "codesign -f -s 'Developer ID Application' --timestamp --deep frodo" + # run: "codesign -f -s 'Developer ID Application: Volker Scheuber (AV6L99G8W9)' --timestamp --deep frodo" + + # + # Zip up the app and add it to the GitHub Release as a + # downloadable asset. + # + + - name: Package for Distribution + run: ditto -V -c -k "frodo" "frodo-macos-${{ needs.build.outputs.newVersion }}.zip" + + - uses: actions/upload-artifact@v3 + with: + name: dist + path: frodo-macos-${{ needs.build.outputs.newVersion }}.zip + + linux-binary-release: + needs: [build, smoke-tests] + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v3 + with: + name: build + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run dist-pkg + + # + # Fail early on failing tests. + # + - name: 'Test' + run: | + ./frodo -v + ./frodo journey -h + ./frodo journey export -h + + - name: Archive distribution binary + run: zip -Z bzip2 frodo-linux-${{ needs.build.outputs.newVersion }}.zip frodo + + - uses: actions/upload-artifact@v3 + with: + name: dist + path: frodo-linux-${{ needs.build.outputs.newVersion }}.zip + + linux-arm64-binary-release: + if: false + needs: [build, smoke-tests] + runs-on: self-hosted + steps: + - uses: actions/download-artifact@v3 + with: + name: build + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run dist-pkg + + # + # Fail early on failing tests. + # + - name: 'Test' + run: | + ./frodo -v + ./frodo journey -h + ./frodo journey export -h + + - name: Archive distribution binary + run: zip -Z bzip2 frodo-linux-arm64-${{ needs.build.outputs.newVersion }}.zip . -i frodo + + - uses: actions/upload-artifact@v3 + with: + name: dist + path: frodo-linux-arm64-${{ needs.build.outputs.newVersion }}.zip + + windows-binary-release: + needs: [build, smoke-tests] + runs-on: windows-latest + steps: + - uses: actions/download-artifact@v3 + with: + name: build + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run dist-pkg + + # + # Fail early on failing tests. + # + - name: 'Test' + run: | + ./frodo.exe -v + ./frodo.exe journey -h + ./frodo.exe journey export -h + + - name: Archive distribution binary + run: 7z a -tzip frodo-win-${{ needs.build.outputs.newVersion }}.zip frodo.exe + + - uses: actions/upload-artifact@v3 + with: + name: dist + path: frodo-win-${{ needs.build.outputs.newVersion }}.zip diff --git a/CHANGELOG.md b/CHANGELOG.md index be319083e..d167f3ad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.24.4-trivir.1] - 2023-05-30 + +## [0.24.4-trivir.0] - 2023-05-30 + +## [0.24.4-trivir.0] - 2023-05-30 + +## [0.24.4-trivir.0] - 2023-05-29 + +## [0.24.4-trivir.0] - 2023-05-29 + +## [0.24.3] - 2023-05-25 + +### Changed + +- Update to frodo-lib 0.19.2 + +## [0.24.2] - 2023-05-22 + ### Added - Support for authorization policies, policy sets, and resource types through new `authz` commands: @@ -65,6 +83,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - \#214: Fixed a regression introduced in #186, which 'swallowed' `frodo` command exit codes and resulted in always exiting with 0 even if a `frodo` command returned with a different exit code. +## [0.24.1] - 2023-05-22 [YANKED] + +## [0.24.1-0] - 2023-05-22 [YANKED] + ## [0.24.0] - 2023-05-21 [YANKED] ## [0.23.1-8] - 2023-05-21 @@ -1170,7 +1192,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed problem with adding connection profiles - Miscellaneous bug fixes -[Unreleased]: https://github.com/rockcarver/frodo-cli/compare/v0.24.1...HEAD +[Unreleased]: https://github.com/trivir/frodo-cli/compare/v0.24.4-trivir.1...HEAD + +[0.24.4-trivir.1]: https://github.com/trivir/frodo-cli/compare/v0.24.4-trivir.0...v0.24.4-trivir.1 + +[0.24.4-trivir.0]: https://github.com/trivir/frodo-cli/compare/v0.24.4-trivir.0...v0.24.4-trivir.0 + +[0.24.4-trivir.0]: https://github.com/trivir/frodo-cli/compare/v0.24.4-trivir.0...v0.24.4-trivir.0 + +[0.24.4-trivir.0]: https://github.com/trivir/frodo-cli/compare/v0.24.4-trivir.0...v0.24.4-trivir.0 + +[0.24.4-trivir.0]: https://github.com/trivir/frodo-cli/compare/v0.24.3...v0.24.4-trivir.0 + +[0.24.3]: https://github.com/rockcarver/frodo-cli/compare/v0.24.1...v0.24.3 + +[0.24.1]: https://github.com/rockcarver/frodo-cli/compare/v0.24.1-0...v0.24.1 + +[0.24.1-0]: https://github.com/rockcarver/frodo-cli/compare/v0.24.1...v0.24.1-0 [0.24.1]: https://github.com/rockcarver/frodo-cli/compare/v0.24.0...v0.24.1 diff --git a/babel.config.cjs.json b/babel.config.cjs.json new file mode 100644 index 000000000..aaaed21e8 --- /dev/null +++ b/babel.config.cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./babel.config.esm.json", + "plugins": [ + ["@babel/plugin-transform-modules-commonjs", { "importInterop": "babel" }], + ["babel-plugin-transform-import-meta"] + ] +} diff --git a/package-lock.json b/package-lock.json index 7b7d2dfe4..1eada40c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@rockcarver/frodo-cli", - "version": "0.24.1", + "version": "0.24.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@rockcarver/frodo-cli", - "version": "0.24.1", + "version": "0.24.3", "license": "MIT", "dependencies": { - "@rockcarver/frodo-lib": "0.19.1", + "@rockcarver/frodo-lib": "0.19.2", "chokidar": "^3.5.3", "cli-progress": "^3.11.2", "cli-table3": "^0.6.3", @@ -2899,9 +2899,9 @@ } }, "node_modules/@rockcarver/frodo-lib": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@rockcarver/frodo-lib/-/frodo-lib-0.19.1.tgz", - "integrity": "sha512-oG27WbGtwDcwiWA287fKUyNpbo1vkXK+VHa2NJfSeUu+dBkl6KgdIKADvoi9AjcRqlyELKKlQ7Z3qLwwKRRutA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@rockcarver/frodo-lib/-/frodo-lib-0.19.2.tgz", + "integrity": "sha512-02gzQiaQLAc1Pi3Sg/uUNZJmL9Hh3sb3e1s/uZMVbiKmowbJ3pLtlG+olLwihd6HSCd0suWE5LZzXBF2yVQZmA==", "dependencies": { "@pollyjs/adapter-node-http": "^6.0.5", "@pollyjs/core": "^6.0.5", diff --git a/package.json b/package.json index b7ef3aa99..d9580872e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@rockcarver/frodo-cli", - "version": "0.24.0", + "name": "@trivir/frodo-cli", + "version": "0.24.4-trivir.1", "type": "module", "description": "A command line interface to manage ForgeRock Identity Cloud tenants, ForgeOps deployments, and classic deployments.", "keywords": [ @@ -29,15 +29,23 @@ }, "main": "esm/launch.js", "scripts": { - "test": "npx tsc && node --experimental-vm-modules node_modules/jest/bin/jest.js", + "rockcarver-frodo-lib": "find src -type f -name \"*.ts\" -exec sed -i \"s#@trivir/frodo-lib#@rockcarver/frodo-lib#g\" {} + && sed -i \"s/@trivir\\/frodo-lib\\//@rockcarver\\/frodo-lib\\//g\" package.json", + "trivir-frodo-lib": "npm uninstall @rockcarver/frodo-lib && npm install @trivir/frodo-lib && find src -type f -name \"*.ts\" -exec sed -i \"s#@rockcarver/frodo-lib#@trivir/frodo-lib#g\" {} + && sed -i \"s/@rockcarver\\/frodo-lib\\//@trivir\\/frodo-lib\\//g\" package.json", + "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", "test:local": "npm run build && node --experimental-vm-modules node_modules/jest/bin/jest.js", "test:debug": "node --no-warnings --experimental-vm-modules --experimental-specifier-resolution=node node_modules/jest/bin/jest.js --verbose=true --silent=false", - "lint": "npx eslint --ext .ts --ignore-path .gitignore .", - "lint:fix": "npx eslint --fix --ext .ts --ignore-path .gitignore .", - "build": "npx tsc && npx gulp", - "build:local": "npx tsc && npx gulp build-local", - "build:binary": "npx tsc && npx gulp build-binary", - "watch": "npx gulp watch" + "lint": "eslint --ext .ts --ignore-path .gitignore .", + "lint:fix": "eslint --fix --ext .ts --ignore-path .gitignore .", + "build": "tsc && npm run build:local && npm run build:binary", + "clean-esm": "rimraf esm", + "transpile-esm": "babel --out-dir esm --extensions \".ts\" --source-maps --config-file ./babel.config.esm.json src", + "build:local": "tsc && npm run clean-esm && npm run transpile-esm && npm run clean-cjs && npm run transpile-cjs", + "clean-cjs": "rimraf cjs", + "transpile-cjs": "babel --out-dir cjs --extensions \".ts\" --source-maps --config-file ./babel.config.cjs.json src && echo {\\\"type\\\": \\\"commonjs\\\"} > cjs/package.json", + "dist-pkg": "pkg -C Gzip -t node18 --config package.json -o frodo cjs/app.js", + "build:binary": "tsc && npm run clean-cjs && npm run transpile-cjs && npm run dist-pkg", + "link-frodo-lib": "npm link ../frodo-lib", + "watch": "npm run link-frodo-lib && babel --watch --out-dir esm --extensions \".ts\" --source-maps --config-file ./babel.config.esm.json src" }, "jest": { "testTimeout": 30000 @@ -87,19 +95,20 @@ }, "pkg": { "assets": [ + "package.json", "node_modules/@rockcarver/frodo-lib/cjs/ops/templates/*.json", "node_modules/@rockcarver/frodo-lib/cjs/ops/templates/**/*.json", "node_modules/@rockcarver/frodo-lib/mocks/**/*.har" ], "scripts": [ - "src/cli/**/*.js", - "src/ops/**/*.js", - "src/storage/**/*.js", - "src/utils/**/*.js" + "cjs/cli/**/*.js", + "cjs/ops/**/*.js", + "cjs/storage/**/*.js", + "cjs/utils/**/*.js" ] }, "dependencies": { - "@rockcarver/frodo-lib": "0.19.1", + "@trivir/frodo-lib": "^0.19.3-trivir.0", "chokidar": "^3.5.3", "cli-progress": "^3.11.2", "cli-table3": "^0.6.3", @@ -116,6 +125,7 @@ "yesno": "^0.4.0" }, "devDependencies": { + "@babel/cli": "^7.21.5", "@babel/eslint-parser": "^7.18.9", "@babel/plugin-syntax-import-assertions": "^7.20.0", "@babel/plugin-transform-modules-commonjs": "^7.19.6", @@ -144,9 +154,11 @@ "gulp-rename": "^2.0.0", "gulp-sourcemaps": "^3.0.0", "jest": "^29.3.1", + "json": "^11.0.0", "map-stream": "^0.0.7", "pkg": "^5.8.0", "prettier": "^2.7.1", + "rimraf": "^5.0.1", "typescript": "^4.9.3" } } diff --git a/src/app.ts b/src/app.ts index de9b68218..911055e12 100755 --- a/src/app.ts +++ b/src/app.ts @@ -33,6 +33,8 @@ const { initConnectionProfiles } = ConnectionProfile; '-v, --version' ); + console.log('test branch'); + printMessage(await getVersions(true), 'text', false); await initConnectionProfiles(); diff --git a/src/cli/conn/conn-save.ts b/src/cli/conn/conn-save.ts index 513c76ae7..b1822b3c8 100644 --- a/src/cli/conn/conn-save.ts +++ b/src/cli/conn/conn-save.ts @@ -3,14 +3,13 @@ import { Option } from 'commander'; import { Authenticate, ConnectionProfile, - Log, ServiceAccount, state, constants, } from '@rockcarver/frodo-lib'; -const { provisionCreds } = Log; import { verboseMessage, printMessage } from '../../utils/Console'; import { addExistingServiceAccount } from '../../ops/ConnectionProfileOps.js'; +import { provisionCreds } from '../../ops/LogOps'; const { getTokens } = Authenticate; const { saveConnectionProfile, addNewServiceAccount } = ConnectionProfile; diff --git a/src/cli/logging/logs-fetch.ts b/src/cli/logging/logs-fetch.ts index 9b6e5a91d..1c3e3aa6c 100644 --- a/src/cli/logging/logs-fetch.ts +++ b/src/cli/logging/logs-fetch.ts @@ -9,8 +9,9 @@ import { } from '@rockcarver/frodo-lib'; import * as config from '../../utils/Config'; import { printMessage } from '../../utils/Console'; +import { fetchLogs, provisionCreds } from '../../ops/LogOps'; -const { provisionCreds, fetchLogs, resolveLevel } = Log; +const { resolveLevel } = Log; const { getConnectionProfile, saveConnectionProfile } = ConnectionProfile; const { getTokens } = Authenticate; diff --git a/src/cli/logging/logs-list.ts b/src/cli/logging/logs-list.ts index e50af270a..e41fe7545 100644 --- a/src/cli/logging/logs-list.ts +++ b/src/cli/logging/logs-list.ts @@ -6,8 +6,9 @@ import { state, } from '@rockcarver/frodo-lib'; import { printMessage, verboseMessage } from '../../utils/Console'; +import { provisionCreds } from '../../ops/LogOps'; -const { provisionCreds, getLogSources } = Log; +const { getLogSources } = Log; const { getConnectionProfile, saveConnectionProfile } = ConnectionProfile; const { getTokens } = Authenticate; diff --git a/src/cli/logging/logs-tail.ts b/src/cli/logging/logs-tail.ts index 8b512b403..4cfa45012 100644 --- a/src/cli/logging/logs-tail.ts +++ b/src/cli/logging/logs-tail.ts @@ -9,8 +9,9 @@ import { } from '@rockcarver/frodo-lib'; import * as config from '../../utils/Config'; import { printMessage } from '../../utils/Console'; +import { provisionCreds, tailLogs } from '../../ops/LogOps'; -const { provisionCreds, tailLogs, resolveLevel } = Log; +const { resolveLevel } = Log; const { getConnectionProfile, saveConnectionProfile } = ConnectionProfile; const { getTokens } = Authenticate; diff --git a/src/ops/LogOps.ts b/src/ops/LogOps.ts new file mode 100644 index 000000000..69d13aa62 --- /dev/null +++ b/src/ops/LogOps.ts @@ -0,0 +1,152 @@ +import { LogEventPayloadSkeleton } from '@rockcarver/frodo-lib/types/api/ApiTypes'; +import { printMessage, verboseMessage } from '../utils/Console'; +import { Log, state } from '@rockcarver/frodo-lib'; + +const { + getDefaultNoiseFilter, + tail, + fetch, + getLogApiKeys, + resolvePayloadLevel, + createAPIKeyAndSecret, +} = Log; + +export async function tailLogs( + source: string, + levels: string[], + txid: string, + cookie: string, + nf: string[] +) { + try { + const logsObject = await tail(source, cookie); + let filteredLogs = []; + const noiseFilter = nf == null ? getDefaultNoiseFilter() : nf; + if (Array.isArray(logsObject.result)) { + filteredLogs = logsObject.result.filter( + (el) => + !noiseFilter.includes( + (el.payload as LogEventPayloadSkeleton).logger + ) && + !noiseFilter.includes(el.type) && + (levels[0] === 'ALL' || levels.includes(resolvePayloadLevel(el))) && + (typeof txid === 'undefined' || + txid === null || + (el.payload as LogEventPayloadSkeleton).transactionId?.includes( + txid + )) + ); + } + + filteredLogs.forEach((e) => { + printMessage(JSON.stringify(e), 'data'); + }); + + setTimeout(() => { + tailLogs(source, levels, txid, logsObject.pagedResultsCookie, nf); + }, 5000); + return null; + } catch (e) { + printMessage(`tail ERROR: tail data error - ${e}`, 'error'); + return `tail ERROR: tail data error - ${e}`; + } +} + +export async function provisionCreds() { + try { + let keyName = `frodo-${state.getUsername()}`; + try { + const keys = await getLogApiKeys(); + for (const key of keys) { + if (key.name === keyName) { + // append current timestamp to name if the named key already exists + keyName = `${keyName}-${new Date().toISOString()}`; + } + } + try { + const resp = await createAPIKeyAndSecret(keyName); + if (resp.name !== keyName) { + printMessage( + `create keys ERROR: could not create log API key ${keyName}`, + 'error' + ); + return null; + } + verboseMessage( + `Created a new log API key [${keyName}] in ${state.getHost()}` + ); + return resp; + } catch (error) { + printMessage( + `create keys ERROR: create keys call returned ${error}`, + 'error' + ); + return null; + } + } catch (error) { + printMessage(`get keys ERROR: get keys call returned ${error}`, 'error'); + } + } catch (e) { + printMessage(`create keys ERROR: create keys data error - ${e}`, 'error'); + return null; + } +} + +export async function fetchLogs( + source: string, + startTs: string, + endTs: string, + levels: string[], + txid: string, + ffString: string, + cookie: string, + nf: string[] +) { + try { + const logsObject = await fetch(source, startTs, endTs, cookie); + let filteredLogs = []; + const noiseFilter = nf == null ? getDefaultNoiseFilter() : nf; + if (Array.isArray(logsObject.result)) { + filteredLogs = logsObject.result.filter( + (el) => + !noiseFilter.includes( + (el.payload as LogEventPayloadSkeleton).logger + ) && + !noiseFilter.includes(el.type) && + (levels[0] === 'ALL' || levels.includes(resolvePayloadLevel(el))) && + (typeof txid === 'undefined' || + txid === null || + (el.payload as LogEventPayloadSkeleton).transactionId?.includes( + txid + )) + ); + } + + filteredLogs.forEach((e) => { + const log = JSON.stringify(e, null, 2); + if (ffString) { + if (log.includes(ffString)) { + printMessage(log, 'data'); + } + } else { + printMessage(log, 'data'); + } + }); + if (logsObject.pagedResultsCookie != null) { + await fetchLogs( + source, + startTs, + endTs, + levels, + txid, + ffString, + logsObject.pagedResultsCookie, + nf + ); + } + return null; + } catch (e) { + printMessage(`fetch ERROR: fetch data error - ${e}`, 'error'); + return `fetch ERROR: fetch data error - ${e}`; + } +} diff --git a/src/utils/Config.ts b/src/utils/Config.ts index 07a3e53b1..94d01b4d8 100644 --- a/src/utils/Config.ts +++ b/src/utils/Config.ts @@ -4,7 +4,7 @@ import { Log } from '@rockcarver/frodo-lib'; import { printMessage } from './Console'; -const { defaultNoiseFilter } = Log; +const { getDefaultNoiseFilter } = Log; export const FRODO_CONFIG_PATH_KEY = 'FRODO_CONFIG_PATH'; export const FRODO_LOG_NOISEFILTER_FILENAME = 'LoggingNoiseFilter.json'; @@ -29,12 +29,12 @@ export function getNoiseFilters(defaults: boolean): Array { const filename = `${getConfigPath()}/${FRODO_LOG_NOISEFILTER_FILENAME}`; if (defaults) { printMessage(`Using default logging noise filters.`, 'info'); - return defaultNoiseFilter(); + return getDefaultNoiseFilter(); } let noiseFilter = getCustomNoiseFilters(); if (noiseFilter.length == 0) { printMessage(`No custom noise filters defined. Using defaults.`, 'info'); - noiseFilter = defaultNoiseFilter(); + noiseFilter = getDefaultNoiseFilter(); try { fs.writeFileSync(filename, JSON.stringify(noiseFilter, null, 2)); printMessage(