diff --git a/.appinspect.manualcheck.yaml b/.appinspect.manualcheck.yaml index 0d26b8f..2d01a29 100644 --- a/.appinspect.manualcheck.yaml +++ b/.appinspect.manualcheck.yaml @@ -59,4 +59,6 @@ check_for_supported_tls: check_for_remote_code_execution_in_javascript: comment: 'Ok' check_python_untrusted_xml_functions: + comment: 'Ok' +check_all_python_files_are_well_formed: comment: 'Ok' \ No newline at end of file diff --git a/.github/workflows/build-appinspect.yml b/.github/workflows/build-appinspect.yml index 8b00f22..2dea3c7 100644 --- a/.github/workflows/build-appinspect.yml +++ b/.github/workflows/build-appinspect.yml @@ -12,7 +12,7 @@ on: jobs: build: name: Bundle the App - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest outputs: app_name: ${{ steps.app.outputs.name }} app_version: ${{ steps.app.outputs.version }} @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -62,7 +62,7 @@ jobs: appinspect-cli: name: appinspect-cli ${{ matrix.tags }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest continue-on-error: true needs: build strategy: @@ -76,7 +76,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: 3.9 - uses: actions/download-artifact@v4 with: name: ${{ needs.build.outputs.app_name }}-${{ needs.build.outputs.app_version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5854d32..63c8aa9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,23 +1,31 @@ -name: Package and Upload Release +name: Release from Changelog on: push: - tags: - - "v[0-9]+.[0-9]+.[0-9]+" + paths: + - "CHANGELOG.md" + branches: + - main # Grants permission to create releases permissions: contents: write jobs: - build-and-release: - name: Build and Upload Release + build: + name: Build the App runs-on: ubuntu-latest + strategy: + matrix: + python-version: [ 3.9 ] + outputs: + artifact_name: ${{ steps.artifact.outputs.name }} + ta_version: ${{ steps.app.outputs.version }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip @@ -52,11 +60,53 @@ jobs: ucc-gen package --path output/${{ steps.app.outputs.name }} shell: bash - # Release Notes to be added manually by editing the Release via UI! - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 + - id: artifact + run: | + echo "name=${{ steps.app.outputs.name }}-${{ steps.app.outputs.version }}-py${{ matrix.python-version }}" >> $GITHUB_OUTPUT + + - uses: actions/upload-artifact@v4 + with: + name: ${{ steps.artifact.outputs.name }} + path: ${{ steps.app.outputs.name }}*.tar.gz + + release: + name: Upload Release + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: - tag_name: ${{ github.ref_name }} - files: ${{ steps.app.outputs.name }}*.tar.gz + name: ${{ needs.build.outputs.artifact_name }} + path: dist + - name: Fetch latest release info from CHANGELOG + id: changelog + uses: release-flow/keep-a-changelog-action@v3 + with: + command: query + version: latest + - name: Validate version consistency + env: + VERSION: ${{ steps.changelog.outputs.version }} + TA_VERSION: ${{ needs.build.outputs.ta_version }} + run: | + if [ "$VERSION" != "$TA_VERSION" ]; then + echo "❌ Add-On and Changelog version mismatch. Did you forget to bump the Add-On version?" + exit 1 + fi + - name: Create GitHub release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: v${{ steps.changelog.outputs.version }} + RELEASE_NOTES: ${{ steps.changelog.outputs.release-notes }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + LATEST_RELEASE=$(gh release view --json tagName --jq '.tagName' 2>/dev/null || echo "v0.0.0") + if [ "$VERSION" == "$LATEST_RELEASE" ]; then + echo "Versions match nothing to do!" + else + echo "Releasing $VERSION" + gh release create $VERSION \ + --title "$VERSION" \ + --notes "$RELEASE_NOTES" \ + dist/*.tar.gz + fi diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86b3790..329c383 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,9 +14,143 @@ concurrency: cancel-in-progress: true jobs: - splunk-test: + splunk-10x: name: Deploy and test the TA - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + version: [10.2.0] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade splunk-packaging-toolkit splunk-add-on-ucc-framework + + - name: Build TA + id: build + run: | + app_version=$(cat "package/app.manifest" | jq -r '.info.id.version') + echo "app_version=${app_version}" >> $GITHUB_OUTPUT + app_id=$(cat "package/app.manifest" | jq -r '.info.id.name') + echo "app_id=${app_id}" >> $GITHUB_OUTPUT + ucc-gen build --ta-version ${app_version} + mkdir -p output/${app_id}/local + cp etc/cicd/inputs.conf output/${app_id}/local + chmod -R +r output + chmod -R go-w output + shell: bash + + - run: docker network create shared-net + + # NOTE: + # Not having services because of: connectivity and volumes mounting + - name: Start Mockoon container + run: | + docker run -d --name mockoon \ + --network shared-net \ + -v ${{ github.workspace }}/tests/genesyscloud_mock.json:/data/mockoon.json \ + -p 3004:3004 \ + mockoon/cli:latest \ + --data /data/mockoon.json --port 3004 --log-transaction + + # NOTE: + # Splunk to be executed as root to avoid errors when toggling inputs states via REST + - name: Start Splunk container + env: + SPLUNK_START_ARGS: "--answer-yes --no-prompt --accept-license --run-as-root" + SPLUNK_GENERAL_TERMS: "--accept-sgt-current-at-splunk-com" + SPLUNK_PASSWORD: password + GENESYSCLOUD_HOST: http://mockoon:3004 + run: | + docker run -d --name splunk \ + --network shared-net \ + -e SPLUNK_START_ARGS="$SPLUNK_START_ARGS" \ + -e SPLUNK_GENERAL_TERMS="$SPLUNK_GENERAL_TERMS" \ + -e SPLUNK_PASSWORD="$SPLUNK_PASSWORD" \ + -e GENESYSCLOUD_HOST="$GENESYSCLOUD_HOST" \ + -v ${{ github.workspace }}/etc/cicd/environment:/etc/environment \ + -v ${{ github.workspace }}/output/${{ steps.build.outputs.app_id }}:/opt/splunk/etc/apps/${{ steps.build.outputs.app_id }} \ + -p 8000:8000 \ + -p 8089:8089 \ + splunk/splunk:${{ matrix.version }} + # Wait for splunk to be up and running (~2min) + sleep 150 + value=$(docker exec splunk printenv GENESYSCLOUD_HOST) + echo "GENESYSCLOUD_HOST=$value" >> $GITHUB_ENV + + # Enable this to troubleshoot errors with the splunk docker + # - name: Debug Splunk Logs + # if: always() + # run: docker logs $(docker ps -a -q --filter ancestor=splunk/splunk:10.2.0) + + - name: Test mockoon is alive + run: | + docker logs mockoon + for i in {1..30}; do + if curl --silent --fail http://localhost:3004/; then + echo "Mockoon is up!" + exit 0 + fi + echo "Waiting for Mockoon..." + sleep 2 + done + echo "Mockoon failed to start" + exit 1 + + - name: Test connectivity from Splunk to Mockoon + run: | + echo "Test whether Splunk is ready..." + EXPECTED="Ansible playbook complete, will begin streaming splunkd_stderr.log" + docker logs splunk 2>&1 | tail -n 20 | grep -F "$EXPECTED" && echo "Found expected line near end of logs." || (echo "Expected line not found." && exit 1) + echo "Test connectivity..." + docker exec splunk curl -v http://mockoon:3004/ || echo "Failed to reach Mockoon from Splunk" + + - name: Run integration tests + env: + GENESYSCLOUD_HOST: http://localhost:3004 + run: | + pip install -r test-requirements.txt + mkdir -p junit + python -m pytest integration/* --junitxml=junit/integration-test-results-${{ matrix.version }}.xml + working-directory: ./tests + + - name: Run functional tests + if: success() + env: + GENESYSCLOUD_HOST: ${{ env.GENESYSCLOUD_HOST }} + run: | + python -m pytest modinput_functional/* --junitxml=junit/test-results-${{ matrix.version }}.xml + working-directory: ./tests + + - name: Exporting Mockoon logs + if: always() + run: | + mkdir -p logs/ + docker logs mockoon > ${{ github.workspace }}/logs/mockoon-${{ matrix.version }}.log 2>&1 + + - name: Upload Mockoon logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: mockoon-logs-${{ matrix.version }} + path: logs/mockoon-${{ matrix.version }}.log + + - uses: dorny/test-reporter@v2 + if: always() + with: + name: Tests Results + path: 'tests/junit/*.xml' + reporter: java-junit + fail-on-error: 'false' + + splunk-9x: + name: Deploy and test the TA + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -25,7 +159,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a5d0ef --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,103 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). + + +## [v0.3.0] - 2025-09-18 + +### Added + +- `Actions Metrics` and `Audit Query` inputs to collect data from the following endpoints ([#36](https://github.com/splunk/genesys_cloud_ta/pull/36)): + - `/api/v2/analytics/actions/aggregates/query`, and + - `/api/v2/audits/query` + +### Changed + +- Details regarding the terraform automation to ingest extra data using the AWS EventBridge integration + + +## [v0.2.2] - 2025-08-12 + +### Added + +- Option to configure start date to the `conversations details` input. This could avoid errors such as the one reported below: too many events in pagination ([#37](https://github.com/splunk/genesys_cloud_ta/pull/37)) + +```bash +Exception when calling ConversationsApi->post_analytics_conversations_details_query: [400] Bad Request - Pagination may not exceed 100000 results. + +Tip: When extracting large chunks of data (multiple days/weeks), maximize pagination performance by querying in smaller intervals. For example, paging through 1am-2am, then 2am-3am, then 3am-4am, and so forth will outperform paging through one large interval that covers the same time frame. +``` + +### Changed + +- Minors in user aggregates input and in the genesys cloud client ([#37](https://github.com/splunk/genesys_cloud_ta/pull/37)) + + +## [v0.2.1] - 2025-06-16 + +### Added + +- Default values to inputs dropdowns ([#35](https://github.com/splunk/genesys_cloud_ta/pull/35)) +- External links in the navigation bar of the TA to provide a quick way to: + - go to documentation ([#35](https://github.com/splunk/genesys_cloud_ta/pull/35)) + - report an issue ([#35](https://github.com/splunk/genesys_cloud_ta/pull/35)) + +### Fixed + +- `NoneType` error thrown under specific circumstances by the `conversation_details` input ([#35](https://github.com/splunk/genesys_cloud_ta/pull/35)) + + +## [v0.2.0] - 2025-05-15 + +### Fixed + +- Reported `NoneType` errors ([#31](https://github.com/splunk/genesys_cloud_ta/pull/31)) + +### Changed + +- Fields in `app.manifest` ([#31](https://github.com/splunk/genesys_cloud_ta/pull/31)) +- Checkpoint strategy (#30, [#31](https://github.com/splunk/genesys_cloud_ta/pull/31)) +- Logging for inputs ([#30](https://github.com/splunk/genesys_cloud_ta/pull/30), [#31](https://github.com/splunk/genesys_cloud_ta/pull/31)) + +### Removed + +- Usage of lookups to avoid issues in distributed environments ([#31](https://github.com/splunk/genesys_cloud_ta/pull/31)) + + +## [v0.1.0] - 2025-04-28 + +### Added + +- Operational input to collect system services status ([#21](https://github.com/splunk/genesys_cloud_ta/pull/21)) +- Custom tab _Configuration / Add More Data_ to inform users about AWS EventBridge integration availability and give some guidance ([#27](https://github.com/splunk/genesys_cloud_ta/pull/27)) +- Genesys Cloud client initialisation via environment variable configuration ([#24](https://github.com/splunk/genesys_cloud_ta/pull/24)) +- Automated tests ([#24](https://github.com/splunk/genesys_cloud_ta/pull/24)) + +### Removed + +- Analytics input `Chat Observations` as per [#19](https://github.com/splunk/genesys_cloud_ta/issues/19) ([#25](https://github.com/splunk/genesys_cloud_ta/pull/25)) + +### Fixed + +- Analytics input `Conversations Metrics` as per [#19](https://github.com/splunk/genesys_cloud_ta/issues/19) ([#25](https://github.com/splunk/genesys_cloud_ta/pull/25)) +- Cloud vetting failure [#23](https://github.com/splunk/genesys_cloud_ta/issues/23) ([#26](https://github.com/splunk/genesys_cloud_ta/pull/26)) + +### Changed + +- Events refactoring pre-indexing for analytic inputs: + - `Queue Observations` ([#27](https://github.com/splunk/genesys_cloud_ta/pull/27)) + - `Conversations Metrics` ([#25](https://github.com/splunk/genesys_cloud_ta/pull/25)) +- Checkpointers for user inputs `User Aggregates` and `User Routing Statuses` ([#24](https://github.com/splunk/genesys_cloud_ta/pull/24)) +- License ([#21](https://github.com/splunk/genesys_cloud_ta/pull/21)) + + +## [v0.0.1] - 2025-03-19 + +### Added + +- Initial version of the Add-On + +### Fixed + +- py3.7 compatibility with GenesysCloud SDK version 221.0.0 ([#4](https://github.com/splunk/genesys_cloud_ta/pull/4)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d4ca4f..23cfd29 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,7 +100,19 @@ $~ make run-functional-tests :point_right: For debugging purposes, you can enable logging to stdout by adding `-o log_cli=true` to the pytest command executed in `run-functional-tests` ## Release the Add-On -A CI/CD workflow will automatically create a release when a tag is pushed to the `main` branch. Please note that **release notes shall be [manually added via UI](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#editing-a-release)** as soon as the workflow has completed. +A CI/CD workflow will automatically create a release. To trigger it: + +- Bump the Add-On version according to [Semantic Versioning](http://semver.org/) in `package/app.manifest` and `globalConfig.json` +- Update the `CHANGELOG` following [guidelines](#changelog) +- Push to `main` + +On push to `main`, the following checks will be executed before releasing a new version of the Add-On: + +- **Build**: Creates app package +- **Sanity Check**: Validates version consistency between the `CHANGELOG` file and the Add-On. They must match. + +### Changelog +A `CHANGELOG.md` file is used to document changes between versions. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## Documentation Documentation made with [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) and served by a CI/CD workflow. diff --git a/docker-compose.yml b/docker-compose.yml index d1b9109..16bd289 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: splunk: - image: "splunk/splunk:latest" + image: "splunk/splunk:9.3.8" platform: "linux/amd64" container_name: genesyscloud volumes: diff --git a/docs/index.md b/docs/index.md index 63b3d69..3476417 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ # Genesys Cloud Add-on for Splunk -| | | -|--------------------------|----------------------| -| Version | 0.3.0 | -| Vendor Products | Genesys Cloud | -| Splunk platform versions | 9.2.x, 9.3.x, 9.4.x | -| Platforms | Platform independent | +| | | +|--------------------------|---------------------------| +| Version | 0.3.0 | +| Vendor Products | Genesys Cloud | +| Splunk platform versions | 9.2.x, 9.3.x, 9.4.x, 10.x | +| Platforms | Platform independent | diff --git a/package/bin/genesyscloud_client.py b/package/bin/genesyscloud_client.py index 5993c97..f1e4317 100644 --- a/package/bin/genesyscloud_client.py +++ b/package/bin/genesyscloud_client.py @@ -9,6 +9,9 @@ class GenesysCloudClient: + """ + Interface with Genesys Cloud + """ client: ApiClient = None def __init__(self, logger: logging.Logger, client_id: str, client_secret: str, aws_region: str):