diff --git a/.generator/schemas/v1/openapi.yaml b/.generator/schemas/v1/openapi.yaml index a1335722ca4..dc6c8110eef 100644 --- a/.generator/schemas/v1/openapi.yaml +++ b/.generator/schemas/v1/openapi.yaml @@ -2875,6 +2875,7 @@ components: - ci_tests - ci_pipelines - incident_analytics + - product_analytics example: logs type: string x-enum-varnames: @@ -2889,6 +2890,7 @@ components: - CI_TESTS - CI_PIPELINES - INCIDENT_ANALYTICS + - PRODUCT_ANALYTICS FormulaAndFunctionMetricAggregation: description: The aggregation methods available for metrics queries. enum: diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 5f50db2f7a5..d3d603bec26 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -56843,6 +56843,40 @@ paths: tags: - DORA Metrics x-codegen-request-body-name: body + /api/v2/dora/deployment/{deployment_id}: + delete: + description: Use this API endpoint to delete a deployment event. + operationId: DeleteDORADeployment + parameters: + - description: The ID of the deployment event to delete. + in: path + name: deployment_id + required: true + schema: + type: string + responses: + '202': + description: Accepted + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Bad Request + '403': + $ref: '#/components/responses/NotAuthorizedResponse' + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + - appKeyAuth: [] + summary: Delete a deployment event + tags: + - DORA Metrics + x-permission: + operator: OR + permissions: + - dora_metrics_write /api/v2/dora/deployments: post: description: Use this API endpoint to get a list of deployment events. @@ -56966,6 +57000,40 @@ paths: tags: - DORA Metrics x-codegen-request-body-name: body + /api/v2/dora/failure/{failure_id}: + delete: + description: Use this API endpoint to delete a failure event. + operationId: DeleteDORAFailure + parameters: + - description: The ID of the failure event to delete. + in: path + name: failure_id + required: true + schema: + type: string + responses: + '202': + description: Accepted + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/JSONAPIErrorResponse' + description: Bad Request + '403': + $ref: '#/components/responses/NotAuthorizedResponse' + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + - appKeyAuth: [] + summary: Delete a failure event + tags: + - DORA Metrics + x-permission: + operator: OR + permissions: + - dora_metrics_write /api/v2/dora/failures: post: description: Use this API endpoint to get a list of failure events. @@ -75655,8 +75723,8 @@ tags: See the [Container Monitoring page](https://docs.datadoghq.com/containers/) for more information. name: Containers -- description: 'Search or send events for DORA Metrics to measure and improve your - software delivery performance. See the [DORA Metrics page](https://docs.datadoghq.com/dora_metrics/) +- description: 'Search, send, or delete events for DORA Metrics to measure and improve + your software delivery performance. See the [DORA Metrics page](https://docs.datadoghq.com/dora_metrics/) for more information. diff --git a/.github/workflows/reusable-ci.yml b/.github/workflows/reusable-ci.yml new file mode 100644 index 00000000000..9f4a3feff75 --- /dev/null +++ b/.github/workflows/reusable-ci.yml @@ -0,0 +1,70 @@ +name: Reusable Complete CI Workflow + +on: + workflow_call: + inputs: + target-branch: + description: 'Branch to checkout and test (defaults to the calling branch)' + required: false + type: string + default: '' + cache-version: + description: 'Cache version for gem dependencies' + required: false + type: string + default: '' + + secrets: + PIPELINE_GITHUB_APP_ID: + required: false + PIPELINE_GITHUB_APP_PRIVATE_KEY: + required: false + # Integration test secrets + DD_API_KEY: + required: false + DD_CLIENT_API_KEY: + required: false + DD_CLIENT_APP_KEY: + required: false + SLEEP_AFTER_REQUEST: + required: false + +jobs: + pre-commit: + uses: ./.github/workflows/reusable-pre-commit.yml + with: + target-branch: ${{ inputs.target-branch }} + enable-commit-changes: false # Don't auto-commit in external CI + secrets: + PIPELINE_GITHUB_APP_ID: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + PIPELINE_GITHUB_APP_PRIVATE_KEY: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} + + test: + uses: ./.github/workflows/reusable-ruby-test.yml + with: + target-branch: ${{ inputs.target-branch }} + cache-version: ${{ inputs.cache-version }} + secrets: + PIPELINE_GITHUB_APP_ID: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + PIPELINE_GITHUB_APP_PRIVATE_KEY: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} + DD_API_KEY: ${{ secrets.DD_API_KEY }} + + examples: + uses: ./.github/workflows/reusable-examples.yml + with: + target-branch: ${{ inputs.target-branch }} + cache-version: ${{ inputs.cache-version }} + + integration: + uses: ./.github/workflows/reusable-integration-test.yml + with: + target-branch: ${{ inputs.target-branch }} + cache-version: ${{ inputs.cache-version }} + secrets: + PIPELINE_GITHUB_APP_ID: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + PIPELINE_GITHUB_APP_PRIVATE_KEY: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} + DD_API_KEY: ${{ secrets.DD_API_KEY }} + DD_CLIENT_API_KEY: ${{ secrets.DD_CLIENT_API_KEY }} + DD_CLIENT_APP_KEY: ${{ secrets.DD_CLIENT_APP_KEY }} + SLEEP_AFTER_REQUEST: ${{ secrets.SLEEP_AFTER_REQUEST }} + diff --git a/.github/workflows/reusable-examples.yml b/.github/workflows/reusable-examples.yml new file mode 100644 index 00000000000..90a2ea764cb --- /dev/null +++ b/.github/workflows/reusable-examples.yml @@ -0,0 +1,45 @@ +name: Reusable Examples Workflow + +on: + workflow_call: + inputs: + target-branch: + description: 'Branch to checkout and test (defaults to the calling branch)' + required: false + type: string + default: '' + examples-script: + description: 'Examples script to execute' + required: false + type: string + default: './check-examples.sh' + cache-version: + description: 'Cache version for gem dependencies' + required: false + type: string + default: '' + +jobs: + examples: + runs-on: ubuntu-latest + if: > + (github.event.pull_request.draft == false && + !contains(github.event.pull_request.labels.*.name, 'ci/skip') && + !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || + github.event_name == 'schedule' + env: + DD_PROFILING_NO_EXTENSION: true + steps: + - uses: actions/checkout@v3 + with: + repository: DataDog/datadog-api-client-ruby + ref: ${{ inputs.target-branch || github.ref }} + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: "2.7" + bundler-cache: true + cache-version: ${{ inputs.cache-version }} + - name: Check examples + run: ${{ inputs.examples-script }} + shell: bash \ No newline at end of file diff --git a/.github/workflows/test_integration.yml b/.github/workflows/reusable-integration-test.yml similarity index 58% rename from .github/workflows/test_integration.yml rename to .github/workflows/reusable-integration-test.yml index 7b641a5f04a..af6d5e6d021 100644 --- a/.github/workflows/test_integration.yml +++ b/.github/workflows/reusable-integration-test.yml @@ -1,10 +1,12 @@ -name: Run Integration Tests +name: Reusable Integration Test Workflow permissions: contents: read on: pull_request: + branches: + - master types: - opened - reopened @@ -12,10 +14,48 @@ on: - synchronize - labeled - unlabeled - branches: - - master schedule: - cron: "0 2 * * *" + workflow_call: + inputs: + target-branch: + description: 'Branch to checkout and test (defaults to the calling branch)' + required: false + type: string + default: '' + enable-status-reporting: + description: 'Whether to post status checks to datadog-api-spec repo' + required: false + type: boolean + default: false + status-context: + description: 'Context for status checks' + required: false + type: string + default: 'integration' + target-repo: + description: 'Repository to post status to' + required: false + type: string + default: 'datadog-api-spec' + cache-version: + description: 'Cache version for gem dependencies' + required: false + type: string + default: '' + secrets: + PIPELINE_GITHUB_APP_ID: + required: false + PIPELINE_GITHUB_APP_PRIVATE_KEY: + required: false + DD_API_KEY: + required: true + DD_CLIENT_API_KEY: + required: true + DD_CLIENT_APP_KEY: + required: true + SLEEP_AFTER_REQUEST: + required: false concurrency: group: integration-${{ github.head_ref }} @@ -48,17 +88,20 @@ jobs: with: app-id: ${{ secrets.PIPELINE_GITHUB_APP_ID }} private-key: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} - repositories: datadog-api-spec + repositories: ${{ inputs.target-repo || 'datadog-api-spec' }} - name: Checkout code uses: actions/checkout@v3 + with: + repository: DataDog/datadog-api-client-ruby + ref: ${{ inputs.target-branch || github.ref }} - name: Post pending status check - if: github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') + if: github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') && (inputs.enable-status-reporting || github.event_name != 'workflow_call') uses: DataDog/github-actions/post-status-check@v2 with: github-token: ${{ steps.get_token.outputs.token }} - repo: datadog-api-spec + repo: ${{ inputs.target-repo || 'datadog-api-spec' }} status: pending - context: integration + context: ${{ inputs.status-context || 'integration' }} - name: Install system zstd run: | sudo apt-get -y install zstd @@ -68,7 +111,7 @@ jobs: with: ruby-version: "3.2" bundler-cache: true - cache-version: ${{ secrets.CACHE_VERSION }} + cache-version: ${{ inputs.cache-version }} - name: Install deps run: bundle install - name: Run integration tests @@ -84,20 +127,20 @@ jobs: DD_TEST_CLIENT_APP_KEY: ${{ secrets.DD_CLIENT_APP_KEY }} DD_TRACE_ANALYTICS_ENABLED: "true" RECORD: "none" - SLEEP_AFTER_REQUEST: "${{ vars.SLEEP_AFTER_REQUEST }}" + SLEEP_AFTER_REQUEST: ${{ secrets.SLEEP_AFTER_REQUEST || vars.SLEEP_AFTER_REQUEST }} - name: Post failure status check - if: failure() && github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') + if: failure() && github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') && (inputs.enable-status-reporting || github.event_name != 'workflow_call') uses: DataDog/github-actions/post-status-check@v2 with: github-token: ${{ steps.get_token.outputs.token }} - repo: datadog-api-spec + repo: ${{ inputs.target-repo || 'datadog-api-spec' }} status: failure - context: integration + context: ${{ inputs.status-context || 'integration' }} - name: Post success status check - if: "!failure() && github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/')" + if: "!failure() && github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') && (inputs.enable-status-reporting || github.event_name != 'workflow_call')" uses: DataDog/github-actions/post-status-check@v2 with: github-token: ${{ steps.get_token.outputs.token }} - repo: datadog-api-spec + repo: ${{ inputs.target-repo || 'datadog-api-spec' }} status: success - context: integration + context: ${{ inputs.status-context || 'integration' }} \ No newline at end of file diff --git a/.github/workflows/reusable-pre-commit.yml b/.github/workflows/reusable-pre-commit.yml new file mode 100644 index 00000000000..a5f80fd5e46 --- /dev/null +++ b/.github/workflows/reusable-pre-commit.yml @@ -0,0 +1,82 @@ +name: Reusable Pre-commit Workflow + +on: + workflow_call: + inputs: + target-branch: + description: 'Branch to checkout and test (defaults to the calling branch)' + required: false + type: string + default: '' + enable-commit-changes: + description: 'Whether to commit and push pre-commit fixes' + required: false + type: boolean + default: true + secrets: + PIPELINE_GITHUB_APP_ID: + required: false + PIPELINE_GITHUB_APP_PRIVATE_KEY: + required: false + +env: + GIT_AUTHOR_EMAIL: "packages@datadoghq.com" + GIT_AUTHOR_NAME: "ci.datadog-api-spec" + +jobs: + pre-commit: + runs-on: ubuntu-latest + if: > + (github.event.pull_request.draft == false && + !contains(github.event.pull_request.labels.*.name, 'ci/skip') && + !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || + github.event_name == 'schedule' + steps: + - name: Get GitHub App token + id: get_token + if: inputs.enable-commit-changes + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + private-key: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + repository: DataDog/datadog-api-client-ruby + ref: ${{ inputs.target-branch || github.event.pull_request.head.sha || github.ref }} + token: ${{ inputs.enable-commit-changes && steps.get_token.outputs.token || github.token }} + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install pre-commit + run: python -m pip install pre-commit + - name: set PY + run: echo "PY=$(python -c 'import platform;print(platform.python_version())')" >> $GITHUB_ENV + - uses: actions/cache@v3 + with: + path: ~/.cache/pre-commit + key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} + - id: pre_commit + name: Run pre-commit + if: github.event.action != 'closed' && github.event.pull_request.merged != true + run: | + pre-commit run --from-ref "${FROM_REF}" --to-ref "${TO_REF}" --show-diff-on-failure --color=always + env: + FROM_REF: ${{ github.event.pull_request.base.sha }} + TO_REF: ${{ github.event.pull_request.head.sha }} + - name: Commit changes + if: ${{ failure() && inputs.enable-commit-changes }} + run: |- + git add -A + git config user.name "${GIT_AUTHOR_NAME}" + git config user.email "${GIT_AUTHOR_EMAIL}" + git commit -m "pre-commit fixes" + git push origin "HEAD:${HEAD_REF}" + exit 1 + env: + HEAD_REF: ${{ github.event.pull_request.head.ref }} + - id: pre_commit_schedule + name: Run pre-commit in schedule + if: github.event_name == 'schedule' + run: | + pre-commit run --all-files --show-diff-on-failure --color=always \ No newline at end of file diff --git a/.github/workflows/reusable-ruby-test.yml b/.github/workflows/reusable-ruby-test.yml new file mode 100644 index 00000000000..77c27046426 --- /dev/null +++ b/.github/workflows/reusable-ruby-test.yml @@ -0,0 +1,66 @@ +name: Reusable Ruby Testing Workflow + +on: + workflow_call: + inputs: + target-branch: + description: 'Branch to checkout and test (defaults to the calling branch)' + required: false + type: string + default: '' + ruby-versions: + description: 'JSON array of Ruby versions to test against' + required: false + type: string + default: '["2.7", "3.2", "jruby-9.4.12.0"]' + platforms: + description: 'JSON array of platforms to run tests on' + required: false + type: string + default: '["ubuntu-latest"]' + test-script: + description: 'Test script to execute' + required: false + type: string + default: './run-tests.sh' + cache-version: + description: 'Cache version for gem dependencies' + required: false + type: string + default: '' + secrets: + PIPELINE_GITHUB_APP_ID: + required: false + PIPELINE_GITHUB_APP_PRIVATE_KEY: + required: false + DD_API_KEY: + required: false + +jobs: + test: + strategy: + matrix: + ruby-version: ${{ fromJSON(inputs.ruby-versions) }} + platform: ${{ fromJSON(inputs.platforms) }} + runs-on: ${{ matrix.platform }} + if: (github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci/skip') && !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || github.event_name == 'schedule' + env: + BUNDLE_WITHOUT: docs + DD_PROFILING_NO_EXTENSION: true + DD_CIVISIBILITY_AGENTLESS_ENABLED: true + DD_ENV: prod + DD_API_KEY: ${{ secrets.DD_API_KEY }} + steps: + - uses: actions/checkout@v3 + with: + repository: DataDog/datadog-api-client-ruby + ref: ${{ inputs.target-branch || github.ref }} + - name: Set up Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + cache-version: ${{ inputs.cache-version }} + - name: Test + run: ${{ inputs.test-script }} + shell: bash diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6bb516eb843..762e1b73741 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,103 +20,45 @@ concurrency: jobs: pre-commit: - runs-on: ubuntu-latest if: > (github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci/skip') && !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || github.event_name == 'schedule' - steps: - - name: Get GitHub App token - id: get_token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.PIPELINE_GITHUB_APP_ID }} - private-key: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - token: ${{ steps.get_token.outputs.token }} - - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - name: Install pre-commit - run: python -m pip install pre-commit - - name: set PY - run: echo "PY=$(python -c 'import platform;print(platform.python_version())')" >> $GITHUB_ENV - - uses: actions/cache@v3 - with: - path: ~/.cache/pre-commit - key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} - - id: pre_commit - name: Run pre-commit - if: github.event.action != 'closed' && github.event.pull_request.merged != true - run: | - pre-commit run --from-ref "${FROM_REF}" --to-ref "${TO_REF}" --show-diff-on-failure --color=always - env: - FROM_REF: ${{ github.event.pull_request.base.sha }} - TO_REF: ${{ github.event.pull_request.head.sha }} - - name: Commit changes - if: ${{ failure() }} - run: |- - git add -A - git config user.name "${GIT_AUTHOR_NAME}" - git config user.email "${GIT_AUTHOR_EMAIL}" - git commit -m "pre-commit fixes" - git push origin "HEAD:${HEAD_REF}" - exit 1 - env: - HEAD_REF: ${{ github.event.pull_request.head.ref }} - - id: pre_commit_schedule - name: Run pre-commit in schedule - if: github.event_name == 'schedule' - run: | - pre-commit run --all-files --show-diff-on-failure --color=always + uses: ./.github/workflows/reusable-pre-commit.yml + with: + enable-commit-changes: true + secrets: + PIPELINE_GITHUB_APP_ID: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + PIPELINE_GITHUB_APP_PRIVATE_KEY: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} test: - strategy: - matrix: - ruby-version: ["2.7", "3.2", "jruby-9.4.12.0"] - platform: [ubuntu-latest] - runs-on: ${{ matrix.platform }} - if: (github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci/skip') && !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || github.event_name == 'schedule' - env: - BUNDLE_WITHOUT: docs - DD_PROFILING_NO_EXTENSION: true - DD_CIVISIBILITY_AGENTLESS_ENABLED: true - DD_ENV: prod + if: > + (github.event.pull_request.draft == false && + !contains(github.event.pull_request.labels.*.name, 'ci/skip') && + !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || + github.event_name == 'schedule' + uses: ./.github/workflows/reusable-ruby-test.yml + with: + ruby-versions: '["2.7", "3.2", "jruby-9.4.12.0"]' + platforms: '["ubuntu-latest"]' + test-script: './run-tests.sh' + cache-version: ${{ vars.CACHE_VERSION }} + secrets: + PIPELINE_GITHUB_APP_ID: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + PIPELINE_GITHUB_APP_PRIVATE_KEY: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} DD_API_KEY: ${{ secrets.DD_API_KEY }} - steps: - - uses: actions/checkout@v3 - - name: Set up Ruby ${{ matrix.ruby-version }} - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby-version }} - bundler-cache: true - # modify repository variable when there are problems with installing gems - cache-version: ${{ vars.CACHE_VERSION }} - - name: Test - run: ./run-tests.sh - shell: bash examples: - runs-on: ubuntu-latest - if: (github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci/skip') && !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || github.event_name == 'schedule' - env: - DD_PROFILING_NO_EXTENSION: true - steps: - - uses: actions/checkout@v3 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: "2.7" - bundler-cache: true - # modify repository variable when there are problems with installing gems - cache-version: ${{ vars.CACHE_VERSION }} - - name: Check examples - run: ./check-examples.sh - shell: bash + if: > + (github.event.pull_request.draft == false && + !contains(github.event.pull_request.labels.*.name, 'ci/skip') && + !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/')) || + github.event_name == 'schedule' + uses: ./.github/workflows/reusable-examples.yml + with: + examples-script: './check-examples.sh' + cache-version: ${{ vars.CACHE_VERSION }} report: runs-on: ubuntu-latest @@ -133,10 +75,10 @@ jobs: app-id: ${{ secrets.PIPELINE_GITHUB_APP_ID }} private-key: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} repositories: datadog-api-spec - - name: Post status 3heck + - name: Post status check uses: DataDog/github-actions/post-status-check@v2 with: github-token: ${{ steps.get_token.outputs.token }} repo: datadog-api-spec - status: ${{ (needs.test.result == 'cancelled' || needs.examples.result == 'cancelled') && 'pending' || needs.test.result == 'success' && needs.examples.result == 'success' && 'success' || 'failure' }} + status: ${{ (needs.test.result == 'cancelled' || needs.examples.result == 'cancelled') && 'pending' || (needs.test.result == 'success' && needs.examples.result == 'success') && 'success' || 'failure' }} context: master/unit diff --git a/cassettes/features/v1/dashboards/Create-a-new-timeseries-widget-with-product-analytics-data-source.frozen b/cassettes/features/v1/dashboards/Create-a-new-timeseries-widget-with-product-analytics-data-source.frozen new file mode 100644 index 00000000000..ccf84dbc10c --- /dev/null +++ b/cassettes/features/v1/dashboards/Create-a-new-timeseries-widget-with-product-analytics-data-source.frozen @@ -0,0 +1 @@ +2025-09-18T18:51:17.951Z \ No newline at end of file diff --git a/cassettes/features/v1/dashboards/Create-a-new-timeseries-widget-with-product-analytics-data-source.yml b/cassettes/features/v1/dashboards/Create-a-new-timeseries-widget-with-product-analytics-data-source.yml new file mode 100644 index 00000000000..3d19d147cd4 --- /dev/null +++ b/cassettes/features/v1/dashboards/Create-a-new-timeseries-widget-with-product-analytics-data-source.yml @@ -0,0 +1,47 @@ +http_interactions: +- recorded_at: Thu, 18 Sep 2025 18:51:17 GMT + request: + body: + encoding: UTF-8 + string: '{"layout_type":"ordered","reflow_type":"auto","title":"Test-Create_a_new_timeseries_widget_with_product_analytics_data_source-1758221477 + with product_analytics datasource","widgets":[{"definition":{"legend_columns":["avg","min","max","value","sum"],"legend_layout":"auto","requests":[{"display_type":"line","formulas":[{"formula":"query1"}],"queries":[{"compute":{"aggregation":"count"},"data_source":"product_analytics","group_by":[],"indexes":["*"],"name":"query1","search":{"query":"test_level:test"}}],"response_format":"timeseries","style":{"line_type":"solid","line_width":"normal","palette":"dog_classic"}}],"show_legend":true,"time":{},"title":"","type":"timeseries"}}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v1/dashboard + response: + body: + encoding: UTF-8 + string: '{"id":"zvr-td5-ppm","title":"Test-Create_a_new_timeseries_widget_with_product_analytics_data_source-1758221477 + with product_analytics datasource","description":null,"author_handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","author_name":"CI + Account","layout_type":"ordered","url":"/dashboard/zvr-td5-ppm/test-createanewtimeserieswidgetwithproductanalyticsdatasource-1758221477-with-pr","template_variables":null,"widgets":[{"definition":{"legend_columns":["avg","min","max","value","sum"],"legend_layout":"auto","requests":[{"display_type":"line","formulas":[{"formula":"query1"}],"queries":[{"compute":{"aggregation":"count"},"data_source":"product_analytics","group_by":[],"indexes":["*"],"name":"query1","search":{"query":"test_level:test"}}],"response_format":"timeseries","style":{"line_type":"solid","line_width":"normal","palette":"dog_classic"}}],"show_legend":true,"time":{},"title":"","type":"timeseries"},"id":6058978575853641}],"notify_list":null,"created_at":"2025-09-18T18:51:18.107135+00:00","modified_at":"2025-09-18T18:51:18.107135+00:00","reflow_type":"auto","restricted_roles":[]}' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +- recorded_at: Thu, 18 Sep 2025 18:51:17 GMT + request: + body: null + headers: + Accept: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v1/dashboard/zvr-td5-ppm + response: + body: + encoding: UTF-8 + string: '{"deleted_dashboard_id":"zvr-td5-ppm"} + + ' + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +recorded_with: VCR 6.0.0 diff --git a/examples/v1/dashboards/CreateDashboard_607525069.rb b/examples/v1/dashboards/CreateDashboard_607525069.rb new file mode 100644 index 00000000000..326ef5713d9 --- /dev/null +++ b/examples/v1/dashboards/CreateDashboard_607525069.rb @@ -0,0 +1,61 @@ +# Create a new timeseries widget with product_analytics data source + +require "datadog_api_client" +api_instance = DatadogAPIClient::V1::DashboardsAPI.new + +body = DatadogAPIClient::V1::Dashboard.new({ + title: "Example-Dashboard with product_analytics datasource", + widgets: [ + DatadogAPIClient::V1::Widget.new({ + definition: DatadogAPIClient::V1::TimeseriesWidgetDefinition.new({ + title: "", + show_legend: true, + legend_layout: DatadogAPIClient::V1::TimeseriesWidgetLegendLayout::AUTO, + legend_columns: [ + DatadogAPIClient::V1::TimeseriesWidgetLegendColumn::AVG, + DatadogAPIClient::V1::TimeseriesWidgetLegendColumn::MIN, + DatadogAPIClient::V1::TimeseriesWidgetLegendColumn::MAX, + DatadogAPIClient::V1::TimeseriesWidgetLegendColumn::VALUE, + DatadogAPIClient::V1::TimeseriesWidgetLegendColumn::SUM, + ], + time: DatadogAPIClient::V1::WidgetLegacyLiveSpan.new({}), + type: DatadogAPIClient::V1::TimeseriesWidgetDefinitionType::TIMESERIES, + requests: [ + DatadogAPIClient::V1::TimeseriesWidgetRequest.new({ + formulas: [ + DatadogAPIClient::V1::WidgetFormula.new({ + formula: "query1", + }), + ], + queries: [ + DatadogAPIClient::V1::FormulaAndFunctionEventQueryDefinition.new({ + data_source: DatadogAPIClient::V1::FormulaAndFunctionEventsDataSource::PRODUCT_ANALYTICS, + name: "query1", + search: DatadogAPIClient::V1::FormulaAndFunctionEventQueryDefinitionSearch.new({ + query: "test_level:test", + }), + indexes: [ + "*", + ], + compute: DatadogAPIClient::V1::FormulaAndFunctionEventQueryDefinitionCompute.new({ + aggregation: DatadogAPIClient::V1::FormulaAndFunctionEventAggregation::COUNT, + }), + group_by: [], + }), + ], + response_format: DatadogAPIClient::V1::FormulaAndFunctionResponseFormat::TIMESERIES, + style: DatadogAPIClient::V1::WidgetRequestStyle.new({ + palette: "dog_classic", + line_type: DatadogAPIClient::V1::WidgetLineType::SOLID, + line_width: DatadogAPIClient::V1::WidgetLineWidth::NORMAL, + }), + display_type: DatadogAPIClient::V1::WidgetDisplayType::LINE, + }), + ], + }), + }), + ], + layout_type: DatadogAPIClient::V1::DashboardLayoutType::ORDERED, + reflow_type: DatadogAPIClient::V1::DashboardReflowType::AUTO, +}) +p api_instance.create_dashboard(body) diff --git a/examples/v2/dora-metrics/DeleteDORADeployment.rb b/examples/v2/dora-metrics/DeleteDORADeployment.rb new file mode 100644 index 00000000000..0e43817413e --- /dev/null +++ b/examples/v2/dora-metrics/DeleteDORADeployment.rb @@ -0,0 +1,5 @@ +# Delete a deployment event returns "Accepted" response + +require "datadog_api_client" +api_instance = DatadogAPIClient::V2::DORAMetricsAPI.new +p api_instance.delete_dora_deployment("NO_VALUE") diff --git a/examples/v2/dora-metrics/DeleteDORAFailure.rb b/examples/v2/dora-metrics/DeleteDORAFailure.rb new file mode 100644 index 00000000000..17c01411d4a --- /dev/null +++ b/examples/v2/dora-metrics/DeleteDORAFailure.rb @@ -0,0 +1,5 @@ +# Delete a failure event returns "Accepted" response + +require "datadog_api_client" +api_instance = DatadogAPIClient::V2::DORAMetricsAPI.new +p api_instance.delete_dora_failure("NO_VALUE") diff --git a/features/scenarios_model_mapping.rb b/features/scenarios_model_mapping.rb index fa53ec24c1e..8dfadba604a 100644 --- a/features/scenarios_model_mapping.rb +++ b/features/scenarios_model_mapping.rb @@ -1745,6 +1745,9 @@ "v2.CreateDORADeployment" => { "body" => "DORADeploymentRequest", }, + "v2.DeleteDORADeployment" => { + "deployment_id" => "String", + }, "v2.ListDORADeployments" => { "body" => "DORAListDeploymentsRequest", }, @@ -1754,6 +1757,9 @@ "v2.CreateDORAFailure" => { "body" => "DORAFailureRequest", }, + "v2.DeleteDORAFailure" => { + "failure_id" => "String", + }, "v2.ListDORAFailures" => { "body" => "DORAListFailuresRequest", }, diff --git a/features/v1/dashboards.feature b/features/v1/dashboards.feature index f267082830d..0d161522e95 100644 --- a/features/v1/dashboards.feature +++ b/features/v1/dashboards.feature @@ -950,6 +950,15 @@ Feature: Dashboards And the response "widgets[0].definition.time.value" is equal to 8 And the response "widgets[0].definition.time.hide_incomplete_cost_data" is equal to true + @team:DataDog/dashboards-backend + Scenario: Create a new timeseries widget with product_analytics data source + Given new "CreateDashboard" request + And body with value {"title":"{{ unique }} with product_analytics datasource","widgets":[{"definition":{"title":"","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"time":{},"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"queries":[{"data_source":"product_analytics","name":"query1","search":{"query":"test_level:test"},"indexes":["*"],"compute":{"aggregation":"count"},"group_by":[]}],"response_format":"timeseries","style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]}}],"layout_type":"ordered","reflow_type":"auto"} + When the request is sent + Then the response status is 200 OK + And the response "widgets[0].definition.requests[0].queries[0].data_source" is equal to "product_analytics" + And the response "widgets[0].definition.requests[0].queries[0].search.query" is equal to "test_level:test" + @generated @skip @team:DataDog/reporting-and-sharing Scenario: Create a shared dashboard returns "Bad Request" response Given new "CreatePublicDashboard" request diff --git a/features/v2/dora_metrics.feature b/features/v2/dora_metrics.feature index acc8230e361..e34092056ca 100644 --- a/features/v2/dora_metrics.feature +++ b/features/v2/dora_metrics.feature @@ -1,7 +1,7 @@ @endpoint(dora-metrics) @endpoint(dora-metrics-v2) Feature: DORA Metrics - Search or send events for DORA Metrics to measure and improve your - software delivery performance. See the [DORA Metrics + Search, send, or delete events for DORA Metrics to measure and improve + your software delivery performance. See the [DORA Metrics page](https://docs.datadoghq.com/dora_metrics/) for more information. **Note**: DORA Metrics are not available in the US1-FED site. @@ -9,6 +9,37 @@ Feature: DORA Metrics Given a valid "apiKeyAuth" key in the system And an instance of "DORAMetrics" API + @skip @team:DataDog/ci-app-backend + Scenario: Delete a deployment event returns "Accepted" response + Given new "DeleteDORADeployment" request + And a valid "appKeyAuth" key in the system + And request contains "deployment_id" parameter with value "NO_VALUE" + When the request is sent + Then the response status is 202 Accepted + + @skip @team:DataDog/ci-app-backend + Scenario: Delete a deployment event returns "Bad Request" response + Given new "DeleteDORADeployment" request + And request contains "deployment_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @skip @team:DataDog/ci-app-backend + Scenario: Delete a failure event returns "Accepted" response + Given new "DeleteDORAFailure" request + And a valid "appKeyAuth" key in the system + And request contains "failure_id" parameter with value "NO_VALUE" + When the request is sent + Then the response status is 202 Accepted + + @skip @team:DataDog/ci-app-backend + Scenario: Delete a failure event returns "Bad Request" response + Given new "DeleteDORAFailure" request + And a valid "appKeyAuth" key in the system + And request contains "failure_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + @generated @skip @team:DataDog/ci-app-backend Scenario: Get a deployment event returns "Bad Request" response Given new "GetDORADeployment" request diff --git a/features/v2/undo.json b/features/v2/undo.json index 7f8336d494c..d864e99bb62 100644 --- a/features/v2/undo.json +++ b/features/v2/undo.json @@ -1064,6 +1064,12 @@ "type": "idempotent" } }, + "DeleteDORADeployment": { + "tag": "DORA Metrics", + "undo": { + "type": "idempotent" + } + }, "ListDORADeployments": { "tag": "DORA Metrics", "undo": { @@ -1082,6 +1088,12 @@ "type": "idempotent" } }, + "DeleteDORAFailure": { + "tag": "DORA Metrics", + "undo": { + "type": "idempotent" + } + }, "ListDORAFailures": { "tag": "DORA Metrics", "undo": { diff --git a/lib/datadog_api_client/v1/models/formula_and_function_events_data_source.rb b/lib/datadog_api_client/v1/models/formula_and_function_events_data_source.rb index a41c6958ae8..b72449f8096 100644 --- a/lib/datadog_api_client/v1/models/formula_and_function_events_data_source.rb +++ b/lib/datadog_api_client/v1/models/formula_and_function_events_data_source.rb @@ -32,5 +32,6 @@ class FormulaAndFunctionEventsDataSource CI_TESTS = "ci_tests".freeze CI_PIPELINES = "ci_pipelines".freeze INCIDENT_ANALYTICS = "incident_analytics".freeze + PRODUCT_ANALYTICS = "product_analytics".freeze end end diff --git a/lib/datadog_api_client/v2/api/dora_metrics_api.rb b/lib/datadog_api_client/v2/api/dora_metrics_api.rb index ae5379e946e..f160fe988ba 100644 --- a/lib/datadog_api_client/v2/api/dora_metrics_api.rb +++ b/lib/datadog_api_client/v2/api/dora_metrics_api.rb @@ -242,6 +242,136 @@ def create_dora_incident_with_http_info(body, opts = {}) return data, status_code, headers end + # Delete a deployment event. + # + # @see #delete_dora_deployment_with_http_info + def delete_dora_deployment(deployment_id, opts = {}) + delete_dora_deployment_with_http_info(deployment_id, opts) + nil + end + + # Delete a deployment event. + # + # Use this API endpoint to delete a deployment event. + # + # @param deployment_id [String] The ID of the deployment event to delete. + # @param opts [Hash] the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def delete_dora_deployment_with_http_info(deployment_id, opts = {}) + + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: DORAMetricsAPI.delete_dora_deployment ...' + end + # verify the required parameter 'deployment_id' is set + if @api_client.config.client_side_validation && deployment_id.nil? + fail ArgumentError, "Missing the required parameter 'deployment_id' when calling DORAMetricsAPI.delete_dora_deployment" + end + # resource path + local_var_path = '/api/v2/dora/deployment/{deployment_id}'.sub('{deployment_id}', CGI.escape(deployment_id.to_s).gsub('%2F', '/')) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['*/*']) + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || [:apiKeyAuth, :appKeyAuth] + + new_options = opts.merge( + :operation => :delete_dora_deployment, + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type, + :api_version => "V2" + ) + + data, status_code, headers = @api_client.call_api(Net::HTTP::Delete, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: DORAMetricsAPI#delete_dora_deployment\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Delete a failure event. + # + # @see #delete_dora_failure_with_http_info + def delete_dora_failure(failure_id, opts = {}) + delete_dora_failure_with_http_info(failure_id, opts) + nil + end + + # Delete a failure event. + # + # Use this API endpoint to delete a failure event. + # + # @param failure_id [String] The ID of the failure event to delete. + # @param opts [Hash] the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def delete_dora_failure_with_http_info(failure_id, opts = {}) + + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: DORAMetricsAPI.delete_dora_failure ...' + end + # verify the required parameter 'failure_id' is set + if @api_client.config.client_side_validation && failure_id.nil? + fail ArgumentError, "Missing the required parameter 'failure_id' when calling DORAMetricsAPI.delete_dora_failure" + end + # resource path + local_var_path = '/api/v2/dora/failure/{failure_id}'.sub('{failure_id}', CGI.escape(failure_id.to_s).gsub('%2F', '/')) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['*/*']) + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || [:apiKeyAuth, :appKeyAuth] + + new_options = opts.merge( + :operation => :delete_dora_failure, + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type, + :api_version => "V2" + ) + + data, status_code, headers = @api_client.call_api(Net::HTTP::Delete, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: DORAMetricsAPI#delete_dora_failure\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # Get a deployment event. # # @see #get_dora_deployment_with_http_info