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.pyBitbucket Server API client with resource and webhook management |
+749/-0 |
integration.pyIntegration config, resource selectors, and integration class |
+57/-0 |
main.pyIntegration entrypoint: resource sync and webhook processor
registration |
+74/-0 |
utils.pyUtility for Bitbucket client initialization from config |
+13/-0 |
__init__.pyWebhook processor module exports |
+9/-0 |
_base.pyBase webhook processor mixin for authentication and event filtering |
+30/-0 |
project.pyProject webhook processor for Bitbucket project events |
+33/-0 |
pull_request.pyPull request webhook processor for Bitbucket PR events |
+45/-0 |
repository.pyRepository webhook processor for Bitbucket repository events |
+38/-0 |
|
| Configuration changes | 3 files
blueprints.jsonPort blueprints for Bitbucket projects, repos, PRs, and users |
+245/-0 |
port-app-config.ymlPort resource mapping configuration for Bitbucket entities |
+73/-0 |
sonar-project.propertiesSonarQube project properties for code analysis |
+2/-0 |
|
| Documentation | 5 files
spec.yamlIntegration specification and configuration schema |
+30/-0 |
README.mdIntegration overview and usage documentation |
+7/-0 |
CONTRIBUTING.mdContribution and local development guidelines |
+7/-0 |
CHANGELOG.mdChangelog for Bitbucket Server integration |
+15/-0 |
.env.exampleExample environment variables for integration setup |
+9/-0 |
|
| Miscellaneous | 2 files
MakefileMakefile for development workflow |
+1/-0 |
debug.pyDebug entrypoint for running the integration |
+4/-0 |
|
| Dependencies | 2 files
poetry.tomlPoetry virtualenv configuration |
+3/-0 |
pyproject.tomlProject dependencies and tool configuration |
+114/-0 |
|
| Tests | 1 files
test_sample.pySample test for integration testing setup |
+2/-0 |
|
| Additional files | 2 files |
Need help?
Type /help how to ... in the comments thread for any questions about Qodo Merge usage.Check out the documentation for more information.
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.
|
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 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:
| Category | Suggestion | 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
|
|
| |