ocean icon indicating copy to clipboard operation
ocean copied to clipboard

[Integration][Bitbucket Server] Add Bitbucket Server integration

Open lordsarcastic opened this issue 6 months ago • 4 comments

User description

Description

What - Add Bitbucket Server integration

Why - To provide Bitbucket Server as an Ocean integration

How -

Type of change

Please leave one option from the following and delete the rest:

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [ ] New feature (non-breaking change which adds functionality)
  • [x] New Integration (non-breaking change which adds a new integration)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] Non-breaking change (fix of existing functionality that will not change current behavior)
  • [ ] Documentation (added/updated documentation)

All tests should be run against the port production environment(using a testing org).

Core testing checklist

  • [ ] Integration able to create all default resources from scratch
  • [ ] Resync finishes successfully
  • [ ] Resync able to create entities
  • [ ] Resync able to update entities
  • [ ] Resync able to detect and delete entities
  • [ ] Scheduled resync able to abort existing resync and start a new one
  • [ ] Tested with at least 2 integrations from scratch
  • [ ] Tested with Kafka and Polling event listeners
  • [ ] Tested deletion of entities that don't pass the selector

Integration testing checklist

  • [ ] Integration able to create all default resources from scratch
  • [ ] Resync able to create entities
  • [ ] Resync able to update entities
  • [ ] Resync able to detect and delete entities
  • [ ] Resync finishes successfully
  • [ ] If new resource kind is added or updated in the integration, add example raw data, mapping and expected result to the examples folder in the integration directory.
  • [ ] If resource kind is updated, run the integration with the example data and check if the expected result is achieved
  • [ ] If new resource kind is added or updated, validate that live-events for that resource are working as expected
  • [ ] Docs PR link here

Preflight checklist

  • [ ] Handled rate limiting
  • [ ] Handled pagination
  • [ ] Implemented the code in async
  • [ ] Support Multi account

Screenshots

Include screenshots from your environment showing how the resources of the integration will look.

API Documentation

Provide links to the API documentation used for this integration.


PR Type

Enhancement, Documentation, Tests


Description

  • Introduce Bitbucket Server integration for Port Ocean

    • Implements resource sync for projects, repositories, pull requests, and users
    • Adds webhook support for project, repository, and pull request events
    • Supports filtering, pagination, and async operations
  • Add resource blueprints and configuration for Port mapping

    • Provides .port/resources/blueprints.json and port-app-config.yml
    • Defines mapping for Bitbucket entities to Port blueprints
  • Include documentation and developer resources

    • Adds README, CONTRIBUTING, and changelog
    • Provides .env.example and integration specification
  • Add initial test and development setup

    • Includes Makefile, pyproject.toml, poetry.toml, and test_sample.py

Changes walkthrough 📝

Relevant files
Enhancement
9 files
client.py
Bitbucket Server API client with resource and webhook management
+749/-0 
integration.py
Integration config, resource selectors, and integration class
+57/-0   
main.py
Integration entrypoint: resource sync and webhook processor
registration
+74/-0   
utils.py
Utility for Bitbucket client initialization from config   
+13/-0   
__init__.py
Webhook processor module exports                                                 
+9/-0     
_base.py
Base webhook processor mixin for authentication and event filtering
+30/-0   
project.py
Project webhook processor for Bitbucket project events     
+33/-0   
pull_request.py
Pull request webhook processor for Bitbucket PR events     
+45/-0   
repository.py
Repository webhook processor for Bitbucket repository events
+38/-0   
Configuration changes
3 files
blueprints.json
Port blueprints for Bitbucket projects, repos, PRs, and users
+245/-0 
port-app-config.yml
Port resource mapping configuration for Bitbucket entities
+73/-0   
sonar-project.properties
SonarQube project properties for code analysis                     
+2/-0     
Documentation
5 files
spec.yaml
Integration specification and configuration schema             
+30/-0   
README.md
Integration overview and usage documentation                         
+7/-0     
CONTRIBUTING.md
Contribution and local development guidelines                       
+7/-0     
CHANGELOG.md
Changelog for Bitbucket Server integration                             
+15/-0   
.env.example
Example environment variables for integration setup           
+9/-0     
Miscellaneous
2 files
Makefile
Makefile for development workflow                                               
+1/-0     
debug.py
Debug entrypoint for running the integration                         
+4/-0     
Dependencies
2 files
poetry.toml
Poetry virtualenv configuration                                                   
+3/-0     
pyproject.toml
Project dependencies and tool configuration                           
+114/-0 
Tests
1 files
test_sample.py
Sample test for integration testing setup                               
+2/-0     
Additional files
2 files
__init__.py [link]   
__init__.py [link]   

Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • lordsarcastic avatar May 19 '25 07:05 lordsarcastic

    CI Feedback 🧐

    (Feedback updated until commit https://github.com/port-labs/ocean/commit/56fcdb776d416941fb3d173e2c70a709dd769533)

    A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

    Action: validate-files

    Failed stage: Check Ocean version 🌊 [❌]

    Failure summary:

    The action failed because the Ocean version in the integrations/bitbucket-server/pyproject.toml file
    is not updated to the latest version (0.23.1). The CI workflow checks if all changed integration
    directories have their port_ocean dependency updated to the latest version, and fails if any are
    outdated. Line 818 shows the specific error: "ERROR: Ocean version in
    integrations/bitbucket-server/pyproject.toml is not updated to latest version -> 0.23.1".

    Relevant error logs:
    1:  ##[group]Runner Image Provisioner
    2:  Hosted Compute Agent
    ...
    
    115:  [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader
    116:  [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || :"
    117:  [command]/usr/bin/git config --local http.https://github.com/.extraheader AUTHORIZATION: basic ***
    118:  ##[endgroup]
    119:  ##[group]Fetching the repository
    120:  [command]/usr/bin/git -c protocol.version=2 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/* +3f12f1a9dea9a3cab118b1881031abc66dbd24fb:refs/remotes/pull/1641/merge
    121:  From https://github.com/port-labs/ocean
    122:  * [new branch]        Github-tj-actions-bug-fix -> origin/Github-tj-actions-bug-fix
    123:  * [new branch]        PORT-10639-add-memray-to-jira-integration -> origin/PORT-10639-add-memray-to-jira-integration
    124:  * [new branch]        PORT-10680-Add-default-actions-for-Jira-integration -> origin/PORT-10680-Add-default-actions-for-Jira-integration
    125:  * [new branch]        PORT-10680-Add-default-actions-for-PagerDuty-integration -> origin/PORT-10680-Add-default-actions-for-PagerDuty-integration
    126:  * [new branch]        PORT-10776-Default-Action-for-Snyk-Ocean-Integration -> origin/PORT-10776-Default-Action-for-Snyk-Ocean-Integration
    127:  * [new branch]        PORT-10933-bug-snyk-ingesting-vulnerabilities-from-wrong-org -> origin/PORT-10933-bug-snyk-ingesting-vulnerabilities-from-wrong-org
    128:  * [new branch]        PORT-11183-fix-starlette-denial-of-service-do-s-via-multipart-form-data -> origin/PORT-11183-fix-starlette-denial-of-service-do-s-via-multipart-form-data
    129:  * [new branch]        PORT-11220-automate-git-tag-when-pushing-a-new-commit-to-main -> origin/PORT-11220-automate-git-tag-when-pushing-a-new-commit-to-main
    130:  * [new branch]        PORT-11682-ocean-handle-and-log-errors-of-client-timeouts-when-interacting-with-port-api-upserting-etc -> origin/PORT-11682-ocean-handle-and-log-errors-of-client-timeouts-when-interacting-with-port-api-upserting-etc
    131:  * [new branch]        PORT-12105-Bug-Pagination-logic-error-in-the-SonarQube-integration -> origin/PORT-12105-Bug-Pagination-logic-error-in-the-SonarQube-integration
    132:  * [new branch]        PORT-12472/gitlab-merge-request-event -> origin/PORT-12472/gitlab-merge-request-event
    ...
    
    141:  * [new branch]        PORT-13687-multiple-token-support -> origin/PORT-13687-multiple-token-support
    142:  * [new branch]        PORT-13768              -> origin/PORT-13768
    143:  * [new branch]        PORT-13777              -> origin/PORT-13777
    144:  * [new branch]        PORT-13991-Bug-Pagerduty-live-events-fails-on-service -> origin/PORT-13991-Bug-Pagerduty-live-events-fails-on-service
    145:  * [new branch]        PORT-14108-ocean-azure-multi-subscription-integration -> origin/PORT-14108-ocean-azure-multi-subscription-integration
    146:  * [new branch]        PORT-14266-ocean-to-use-new-bulk-inserts-route -> origin/PORT-14266-ocean-to-use-new-bulk-inserts-route
    147:  * [new branch]        PORT-14408-Add-Support-For-OAuth2-Authentication -> origin/PORT-14408-Add-Support-For-OAuth2-Authentication
    148:  * [new branch]        PORT-14421              -> origin/PORT-14421
    149:  * [new branch]        PORT-14435              -> origin/PORT-14435
    150:  * [new branch]        PORT-14506              -> origin/PORT-14506
    151:  * [new branch]        PORT-14508              -> origin/PORT-14508
    152:  * [new branch]        PORT-14509              -> origin/PORT-14509
    153:  * [new branch]        PORT-14511              -> origin/PORT-14511
    154:  * [new branch]        PORT-14512              -> origin/PORT-14512
    155:  * [new branch]        PORT-14517              -> origin/PORT-14517
    156:  * [new branch]        PORT-14522-Bug-422-Error-in-Opsgenie-integration-related-to-number-of-incidents-ingested -> origin/PORT-14522-Bug-422-Error-in-Opsgenie-integration-related-to-number-of-incidents-ingested
    157:  * [new branch]        PORT-14554-Prepare-A-Script-To-Remove-Dangling-Entities -> origin/PORT-14554-Prepare-A-Script-To-Remove-Dangling-Entities
    158:  * [new branch]        PORT-14639              -> origin/PORT-14639
    159:  * [new branch]        PORT-14640-shutting-down-gracefully-on-ocean-resync-exception -> origin/PORT-14640-shutting-down-gracefully-on-ocean-resync-exception
    160:  * [new branch]        PORT-14790-ocean-remove-comments-from-endpoint -> origin/PORT-14790-ocean-remove-comments-from-endpoint
    161:  * [new branch]        PORT-4308-ocean-support-pydantic-v-2 -> origin/PORT-4308-ocean-support-pydantic-v-2
    162:  * [new branch]        PORT-8504-add-configurable-limit-for-wiz-import-issues -> origin/PORT-8504-add-configurable-limit-for-wiz-import-issues
    163:  * [new branch]        PORT-8596-add-the-ability-to-ingest-ami-images-and-acm-certificate-from-aws-new-integration-into-port -> origin/PORT-8596-add-the-ability-to-ingest-ami-images-and-acm-certificate-from-aws-new-integration-into-port
    164:  * [new branch]        PORT-8788-Add-deployment-method-requirements-field -> origin/PORT-8788-Add-deployment-method-requirements-field
    165:  * [new branch]        PORT-9072               -> origin/PORT-9072
    166:  * [new branch]        PORT-9097-ocean-icons-are-not-synced -> origin/PORT-9097-ocean-icons-are-not-synced
    167:  * [new branch]        PORT-9326-bug-sonarqube-integration-throws-errors -> origin/PORT-9326-bug-sonarqube-integration-throws-errors
    168:  * [new branch]        PORT-9612-add-sonar-project-properties-file-to-ocean-integration-code-base -> origin/PORT-9612-add-sonar-project-properties-file-to-ocean-integration-code-base
    ...
    
    230:  * [new branch]        feat-remove-polling-logs -> origin/feat-remove-polling-logs
    231:  * [new branch]        feat/bitbucket          -> origin/feat/bitbucket
    232:  * [new branch]        feat/port-7767-support-exporting-jira-issues-by-sprint -> origin/feat/port-7767-support-exporting-jira-issues-by-sprint
    233:  * [new branch]        feature-bump-single-integration -> origin/feature-bump-single-integration
    234:  * [new branch]        feature/add-docs-sync-workflow -> origin/feature/add-docs-sync-workflow
    235:  * [new branch]        fetch_and_jq            -> origin/fetch_and_jq
    236:  * [new branch]        fix-dev-komodor-integration -> origin/fix-dev-komodor-integration
    237:  * [new branch]        fix-memory-leak-with-fastapi -> origin/fix-memory-leak-with-fastapi
    238:  * [new branch]        fix-unexpected-lack-of-config -> origin/fix-unexpected-lack-of-config
    239:  * [new branch]        fix/strip-app-host      -> origin/fix/strip-app-host
    240:  * [new branch]        format_url_types        -> origin/format_url_types
    241:  * [new branch]        gitlab-param-change     -> origin/gitlab-param-change
    242:  * [new branch]        gitlab-v2               -> origin/gitlab-v2
    243:  * [new branch]        jira-oauth-support      -> origin/jira-oauth-support
    244:  * [new branch]        jortegac/main           -> origin/jortegac/main
    245:  * [new branch]        jq_next-assertion-error -> origin/jq_next-assertion-error
    246:  * [new branch]        label-prs               -> origin/label-prs
    247:  * [new branch]        main                    -> origin/main
    248:  * [new branch]        mapping_rule_schema_fix -> origin/mapping_rule_schema_fix
    249:  * [new branch]        oauth-token-refresh-by-error-mode -> origin/oauth-token-refresh-by-error-mode
    250:  * [new branch]        ocean_11_memo_leak      -> origin/ocean_11_memo_leak
    ...
    
    584:  Downloading xmltodict-0.14.2-py2.py3-none-any.whl (10.0 kB)
    585:  Installing collected packages: xmltodict, typing-extensions, tomlkit, shellingham, regex, PyYAML, pygments, packaging, mdurl, click, argcomplete, yq, markdown-it-py, rich, typer, toml-cli
    586:  Successfully installed PyYAML-6.0.2 argcomplete-3.6.2 click-8.2.1 markdown-it-py-3.0.0 mdurl-0.1.2 packaging-25.0 pygments-2.19.1 regex-2024.11.6 rich-14.0.0 shellingham-1.5.4 toml-cli-0.7.0 tomlkit-0.13.2 typer-0.16.0 typing-extensions-4.13.2 xmltodict-0.14.2 yq-3.4.3
    587:  ##[group]Run git remote add ocean-origin https://github.com/port-labs/ocean.git
    588:  [36;1mgit remote add ocean-origin https://github.com/port-labs/ocean.git[0m
    589:  [36;1mgit fetch ocean-origin[0m
    590:  [36;1mchanged_dirs=$(git diff --name-only ocean-origin/main HEAD | grep 'integrations/' | cut -d'/' -f 1,2 | sort -u)[0m
    591:  [36;1mpackage_version=$(curl -s https://pypi.org/pypi/port-ocean/json | jq -r '.info.version')[0m
    592:  [36;1mfor dir in $changed_dirs; do[0m
    593:  [36;1m  pyproject_file=$(find $dir -name 'pyproject.toml' -not -path "**/.venv/*")[0m
    594:  [36;1m  if [ -n "$pyproject_file" ]; then[0m
    595:  [36;1m    installed_version=$(toml get  tool.poetry.dependencies.port_ocean.version --toml-path $pyproject_file)[0m
    596:  [36;1m    is_version_updated=$(python -c "from packaging import version;print(version.parse('$installed_version'.lstrip('^')) >= version.parse('$package_version'))")[0m
    597:  [36;1m[0m
    598:  [36;1m    if [ "$is_version_updated" = "False" ]; then[0m
    599:  [36;1m      echo "ERROR: Ocean version in $pyproject_file is not updated to latest version -> $package_version"[0m
    600:  [36;1m      exit 1[0m
    ...
    
    609:  PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.12.10/x64/lib/pkgconfig
    610:  Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.10/x64
    611:  Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.10/x64
    612:  Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.10/x64
    613:  LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.12.10/x64/lib
    614:  ##[endgroup]
    615:  From https://github.com/port-labs/ocean
    616:  * [new branch]        Github-tj-actions-bug-fix -> ocean-origin/Github-tj-actions-bug-fix
    617:  * [new branch]        PORT-10639-add-memray-to-jira-integration -> ocean-origin/PORT-10639-add-memray-to-jira-integration
    618:  * [new branch]        PORT-10680-Add-default-actions-for-Jira-integration -> ocean-origin/PORT-10680-Add-default-actions-for-Jira-integration
    619:  * [new branch]        PORT-10680-Add-default-actions-for-PagerDuty-integration -> ocean-origin/PORT-10680-Add-default-actions-for-PagerDuty-integration
    620:  * [new branch]        PORT-10776-Default-Action-for-Snyk-Ocean-Integration -> ocean-origin/PORT-10776-Default-Action-for-Snyk-Ocean-Integration
    621:  * [new branch]        PORT-10933-bug-snyk-ingesting-vulnerabilities-from-wrong-org -> ocean-origin/PORT-10933-bug-snyk-ingesting-vulnerabilities-from-wrong-org
    622:  * [new branch]        PORT-11183-fix-starlette-denial-of-service-do-s-via-multipart-form-data -> ocean-origin/PORT-11183-fix-starlette-denial-of-service-do-s-via-multipart-form-data
    623:  * [new branch]        PORT-11220-automate-git-tag-when-pushing-a-new-commit-to-main -> ocean-origin/PORT-11220-automate-git-tag-when-pushing-a-new-commit-to-main
    624:  * [new branch]        PORT-11682-ocean-handle-and-log-errors-of-client-timeouts-when-interacting-with-port-api-upserting-etc -> ocean-origin/PORT-11682-ocean-handle-and-log-errors-of-client-timeouts-when-interacting-with-port-api-upserting-etc
    625:  * [new branch]        PORT-12105-Bug-Pagination-logic-error-in-the-SonarQube-integration -> ocean-origin/PORT-12105-Bug-Pagination-logic-error-in-the-SonarQube-integration
    626:  * [new branch]        PORT-12472/gitlab-merge-request-event -> ocean-origin/PORT-12472/gitlab-merge-request-event
    ...
    
    635:  * [new branch]        PORT-13687-multiple-token-support -> ocean-origin/PORT-13687-multiple-token-support
    636:  * [new branch]        PORT-13768           -> ocean-origin/PORT-13768
    637:  * [new branch]        PORT-13777           -> ocean-origin/PORT-13777
    638:  * [new branch]        PORT-13991-Bug-Pagerduty-live-events-fails-on-service -> ocean-origin/PORT-13991-Bug-Pagerduty-live-events-fails-on-service
    639:  * [new branch]        PORT-14108-ocean-azure-multi-subscription-integration -> ocean-origin/PORT-14108-ocean-azure-multi-subscription-integration
    640:  * [new branch]        PORT-14266-ocean-to-use-new-bulk-inserts-route -> ocean-origin/PORT-14266-ocean-to-use-new-bulk-inserts-route
    641:  * [new branch]        PORT-14408-Add-Support-For-OAuth2-Authentication -> ocean-origin/PORT-14408-Add-Support-For-OAuth2-Authentication
    642:  * [new branch]        PORT-14421           -> ocean-origin/PORT-14421
    643:  * [new branch]        PORT-14435           -> ocean-origin/PORT-14435
    644:  * [new branch]        PORT-14506           -> ocean-origin/PORT-14506
    645:  * [new branch]        PORT-14508           -> ocean-origin/PORT-14508
    646:  * [new branch]        PORT-14509           -> ocean-origin/PORT-14509
    647:  * [new branch]        PORT-14511           -> ocean-origin/PORT-14511
    648:  * [new branch]        PORT-14512           -> ocean-origin/PORT-14512
    649:  * [new branch]        PORT-14517           -> ocean-origin/PORT-14517
    650:  * [new branch]        PORT-14522-Bug-422-Error-in-Opsgenie-integration-related-to-number-of-incidents-ingested -> ocean-origin/PORT-14522-Bug-422-Error-in-Opsgenie-integration-related-to-number-of-incidents-ingested
    651:  * [new branch]        PORT-14554-Prepare-A-Script-To-Remove-Dangling-Entities -> ocean-origin/PORT-14554-Prepare-A-Script-To-Remove-Dangling-Entities
    652:  * [new branch]        PORT-14639           -> ocean-origin/PORT-14639
    653:  * [new branch]        PORT-14640-shutting-down-gracefully-on-ocean-resync-exception -> ocean-origin/PORT-14640-shutting-down-gracefully-on-ocean-resync-exception
    654:  * [new branch]        PORT-14790-ocean-remove-comments-from-endpoint -> ocean-origin/PORT-14790-ocean-remove-comments-from-endpoint
    655:  * [new branch]        PORT-4308-ocean-support-pydantic-v-2 -> ocean-origin/PORT-4308-ocean-support-pydantic-v-2
    656:  * [new branch]        PORT-8504-add-configurable-limit-for-wiz-import-issues -> ocean-origin/PORT-8504-add-configurable-limit-for-wiz-import-issues
    657:  * [new branch]        PORT-8596-add-the-ability-to-ingest-ami-images-and-acm-certificate-from-aws-new-integration-into-port -> ocean-origin/PORT-8596-add-the-ability-to-ingest-ami-images-and-acm-certificate-from-aws-new-integration-into-port
    658:  * [new branch]        PORT-8788-Add-deployment-method-requirements-field -> ocean-origin/PORT-8788-Add-deployment-method-requirements-field
    659:  * [new branch]        PORT-9072            -> ocean-origin/PORT-9072
    660:  * [new branch]        PORT-9097-ocean-icons-are-not-synced -> ocean-origin/PORT-9097-ocean-icons-are-not-synced
    661:  * [new branch]        PORT-9326-bug-sonarqube-integration-throws-errors -> ocean-origin/PORT-9326-bug-sonarqube-integration-throws-errors
    662:  * [new branch]        PORT-9612-add-sonar-project-properties-file-to-ocean-integration-code-base -> ocean-origin/PORT-9612-add-sonar-project-properties-file-to-ocean-integration-code-base
    ...
    
    724:  * [new branch]        feat-remove-polling-logs -> ocean-origin/feat-remove-polling-logs
    725:  * [new branch]        feat/bitbucket       -> ocean-origin/feat/bitbucket
    726:  * [new branch]        feat/port-7767-support-exporting-jira-issues-by-sprint -> ocean-origin/feat/port-7767-support-exporting-jira-issues-by-sprint
    727:  * [new branch]        feature-bump-single-integration -> ocean-origin/feature-bump-single-integration
    728:  * [new branch]        feature/add-docs-sync-workflow -> ocean-origin/feature/add-docs-sync-workflow
    729:  * [new branch]        fetch_and_jq         -> ocean-origin/fetch_and_jq
    730:  * [new branch]        fix-dev-komodor-integration -> ocean-origin/fix-dev-komodor-integration
    731:  * [new branch]        fix-memory-leak-with-fastapi -> ocean-origin/fix-memory-leak-with-fastapi
    732:  * [new branch]        fix-unexpected-lack-of-config -> ocean-origin/fix-unexpected-lack-of-config
    733:  * [new branch]        fix/strip-app-host   -> ocean-origin/fix/strip-app-host
    734:  * [new branch]        format_url_types     -> ocean-origin/format_url_types
    735:  * [new branch]        gitlab-param-change  -> ocean-origin/gitlab-param-change
    736:  * [new branch]        gitlab-v2            -> ocean-origin/gitlab-v2
    737:  * [new branch]        jira-oauth-support   -> ocean-origin/jira-oauth-support
    738:  * [new branch]        jortegac/main        -> ocean-origin/jortegac/main
    739:  * [new branch]        jq_next-assertion-error -> ocean-origin/jq_next-assertion-error
    740:  * [new branch]        label-prs            -> ocean-origin/label-prs
    741:  * [new branch]        main                 -> ocean-origin/main
    742:  * [new branch]        mapping_rule_schema_fix -> ocean-origin/mapping_rule_schema_fix
    743:  * [new branch]        oauth-token-refresh-by-error-mode -> ocean-origin/oauth-token-refresh-by-error-mode
    744:  * [new branch]        ocean_11_memo_leak   -> ocean-origin/ocean_11_memo_leak
    ...
    
    803:  * [new branch]        snyk-upgrade-b095d1b1d15c37ad9b27e5ad340d9478 -> ocean-origin/snyk-upgrade-b095d1b1d15c37ad9b27e5ad340d9478
    804:  * [new branch]        snyk-upgrade-bfd8d053c19439c4e38f45827827ea7e -> ocean-origin/snyk-upgrade-bfd8d053c19439c4e38f45827827ea7e
    805:  * [new branch]        snyk-upgrade-c0cc22d8bc9a14f9f9b16f4f2601f29d -> ocean-origin/snyk-upgrade-c0cc22d8bc9a14f9f9b16f4f2601f29d
    806:  * [new branch]        snyk-upgrade-c360637938d20f9dc0bfa4b8e6e9c425 -> ocean-origin/snyk-upgrade-c360637938d20f9dc0bfa4b8e6e9c425
    807:  * [new branch]        snyk-upgrade-c4308db9fedbf20f486a386e785bcec5 -> ocean-origin/snyk-upgrade-c4308db9fedbf20f486a386e785bcec5
    808:  * [new branch]        snyk-upgrade-d18f88847cd5952ae3466151a60ac401 -> ocean-origin/snyk-upgrade-d18f88847cd5952ae3466151a60ac401
    809:  * [new branch]        snyk-upgrade-d3b08700f6c7b35ad696d6e0ccbb7c19 -> ocean-origin/snyk-upgrade-d3b08700f6c7b35ad696d6e0ccbb7c19
    810:  * [new branch]        snyk-upgrade-e030c59e680e225c2560aa5c7c7fb864 -> ocean-origin/snyk-upgrade-e030c59e680e225c2560aa5c7c7fb864
    811:  * [new branch]        snyk-upgrade-ec34358e4330c12b9936c44978129497 -> ocean-origin/snyk-upgrade-ec34358e4330c12b9936c44978129497
    812:  * [new branch]        snyk-upgrade-ef6788d7d595933a67b7b289999f37ee -> ocean-origin/snyk-upgrade-ef6788d7d595933a67b7b289999f37ee
    813:  * [new branch]        snyk-upgrade-ff035b88aaaed39de6c7f6b33c85f98d -> ocean-origin/snyk-upgrade-ff035b88aaaed39de6c7f6b33c85f98d
    814:  * [new branch]        test-fastapi         -> ocean-origin/test-fastapi
    815:  * [new branch]        test-pr              -> ocean-origin/test-pr
    816:  * [new branch]        update-depdendencies -> ocean-origin/update-depdendencies
    817:  * [new branch]        upserts_no_save      -> ocean-origin/upserts_no_save
    818:  ERROR: Ocean version in integrations/bitbucket-server/pyproject.toml is not updated to latest version -> 0.23.1
    819:  ##[error]Process completed with exit code 1.
    820:  Post job cleanup.
    
    

    qodo-merge-pro[bot] avatar May 19 '25 07:05 qodo-merge-pro[bot]

    This pull request is automatically being deployed by Amplify Hosting (learn more).

    Access this pull request here: https://pr-1641.d1ftd8v2gowp8w.amplifyapp.com

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 Security concerns

    Sensitive information exposure:
    The client.py file logs the full payload of API requests at line 111, which could potentially include sensitive information. This logging should be removed or sanitized to prevent exposing credentials or other sensitive data in logs.

    ⚡ Recommended focus areas for review

    Rate Limiting

    The rate limiter is configured for 1000 requests per hour, but the implementation might not handle Bitbucket Server's rate limiting correctly. The code comments reference Bitbucket Cloud documentation, but this integration is for Bitbucket Server which may have different rate limiting policies.

    # Rate limit docs: https://support.atlassian.com/bitbucket-cloud/docs/api-request-limits/
    BITBUCKET_RATE_LIMIT = 1000  # requests per hour
    BITBUCKET_RATE_LIMIT_WINDOW = 3600  # 1 hour
    README_PATTERN = re.compile(r"^readme(\.[a-z0-9]+)?$", re.IGNORECASE)
    
    Error Handling

    The get_repository_readme method doesn't properly handle errors when fetching README files. If an error occurs during the API call, it will propagate instead of gracefully returning an empty string.

    async def get_repository_readme(self, project_key: str, repo_slug: str) -> str:
        """
        Get the README content for a specific repository, regardless of casing or extension.
        """
    
        async def find_readme_file() -> str | None:
            file_listing_path = f"projects/{project_key}/repos/{repo_slug}/files"
            async for batch in self.get_paginated_resource(
                file_listing_path, page_size=500
            ):
                for file_path in batch:
                    if "/" not in file_path and README_PATTERN.match(file_path):
                        return file_path
    
            return None
    
        def parse_repository_file_response(file_response: Dict[str, Any]) -> str:
            lines = file_response.get("lines", [])
            return "\n".join(line.get("text", "") for line in lines)
    
        readme_filename = await find_readme_file()
        if not readme_filename:
            return ""
        file_path = f"projects/{project_key}/repos/{repo_slug}/browse/{readme_filename}"
        readme_content = ""
    
        async for readme_file_batch in self.get_paginated_resource(
            path=file_path, page_size=500, full_response=True
        ):
            readme_content += parse_repository_file_response(readme_file_batch)
    
        return readme_content
    
    Authentication Bypass

    The authenticate method always returns True without performing any actual authentication, which could allow unauthorized webhook requests to be processed.

    async def authenticate(
        self, payload: dict[str, Any], headers: dict[str, str]
    ) -> Coroutine[Any, Any, bool]:
        return True
    

    qodo-merge-pro[bot] avatar May 20 '25 12:05 qodo-merge-pro[bot]

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Security
    Fix webhook signature verification
    Suggestion Impact:The commit implemented exactly what was suggested - adding code to check if the signature starts with 'sha256=' and prepending it if not, ensuring compatibility with different signature formats

    code diff:

    +        if not signature.startswith("sha256="):
    +            signature = "sha256=" + signature
    +
    

    The webhook signature verification is using a constant-time comparison with
    hmac.compare_digest(), but the signature format may not match Bitbucket Server's
    format. Bitbucket Server typically sends signatures with the format
    "sha256=hash", but your code assumes the raw signature is passed. Add a check to
    handle both formats.

    integrations/bitbucket-server/client.py [710-735]

     async def verify_webhook_signature(self, request: Request) -> bool:
         """
         Verify webhook request signature.
     
         Args:
             request: Incoming webhook request
     
         Returns:
             True if signature is valid, False otherwise
         """
         if not self.webhook_secret:
             logger.warning(
                 "No secret provided for authenticating incoming webhooks, skipping authentication."
             )
             return True
     
         signature = request.headers.get("x-hub-signature")
         if not signature:
             logger.error("No signature found in request")
             return False
     
         body = await request.body()
         hash_object = hmac.new(self.webhook_secret.encode(), body, hashlib.sha256)
         expected_signature = "sha256=" + hash_object.hexdigest()
    +    
    +    # Handle case where signature might already include the prefix
    +    if not signature.startswith("sha256="):
    +        signature = "sha256=" + signature
     
         return hmac.compare_digest(signature, expected_signature)
    

    [Suggestion processed]

    Suggestion importance[1-10]: 7

    __

    Why: The suggestion improves compatibility with possible variations in the signature header format, which could prevent subtle security or verification bugs. However, the impact is moderate since the original code already covers the expected format for most cases, and this is a defensive enhancement rather than a critical fix.

    Medium
    Possible issue
    Fix return type annotation
    Suggestion Impact:The commit implemented exactly what was suggested - changing the return type annotation of the authenticate method from Coroutine[Any, Any, bool] to bool to match the actual implementation. The commit also removed the unused Coroutine import.

    code diff:

    -from typing import Any, Coroutine
    +from typing import Any
     
     from port_ocean.core.handlers.webhook.abstract_webhook_processor import (
         AbstractWebhookProcessor,
    @@ -14,7 +14,7 @@
     
         async def authenticate(
             self, payload: dict[str, Any], headers: dict[str, str]
    -    ) -> Coroutine[Any, Any, bool]:
    +    ) -> bool:
             return True
    

    The authenticate method is incorrectly returning a boolean value directly
    instead of a coroutine as specified in the return type annotation. This can
    cause runtime errors when the method is called expecting a coroutine.

    integrations/bitbucket-server/webhook_processors/_base.py [15-18]

     async def authenticate(
         self, payload: dict[str, Any], headers: dict[str, str]
    -) -> Coroutine[Any, Any, bool]:
    +) -> bool:
         return True
    

    [Suggestion processed]

    Suggestion importance[1-10]: 6

    __

    Why: The suggestion corrects the return type annotation to match the actual implementation, preventing confusion and potential runtime issues. This is a minor but useful fix for code clarity and correctness.

    Low
    • [ ] Update

    qodo-merge-pro[bot] avatar May 20 '25 12:05 qodo-merge-pro[bot]