Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉 New Source - Xero [python cdk] #18666

Merged
merged 11 commits into from
Nov 11, 2022
Merged

Conversation

alkali
Copy link
Contributor

@alkali alkali commented Oct 30, 2022

What

New source for Xero (as it's accounting software, it supports Accounting API only)

How

I've used Python CDK as there are some data transformations.

Pre-merge Checklist

Expand the relevant checklist and delete the others.

New Connector

Community member or Airbyter

  • Community member? Grant edit access to maintainers (instructions)
  • Secrets in the connector's spec are annotated with airbyte_secret
  • Unit & integration tests added and passing. Community members, please provide proof of success locally e.g: screenshot or copy-paste unit, integration, and acceptance test output. To run acceptance tests for a Python connector, follow instructions in the README. For java connectors run ./gradlew :airbyte-integrations:connectors:<name>:integrationTest.
  • Code reviews completed
  • Documentation updated
    • Connector's README.md
    • Connector's bootstrap.md. See description and examples
    • docs/integrations/<source or destination>/<name>.md including changelog. See changelog example
    • docs/integrations/README.md
    • airbyte-integrations/builds.md
  • PR name follows PR naming conventions

Airbyter

If this is a community PR, the Airbyte engineer reviewing this PR is responsible for the below items.

  • Create a non-forked branch based on this PR and test the below items on it
  • Build is successful
  • If new credentials are required for use in CI, add them to GSM. Instructions.
  • /test connector=connectors/<name> command is passing
  • New Connector version released on Dockerhub by running the /publish command described here
  • After the connector is published, connector added to connector index as described here
  • Seed specs have been re-generated by building the platform and committing the changes to the seed spec files, as described here

Tests

Unit
Test session starts (platform: darwin, Python 3.9.12, pytest 6.1.2, pytest-sugar 0.9.5)
cachedir: .pytest_cache
plugins: hypothesis-6.54.6, sugar-0.9.5, requests-mock-1.9.3, mock-3.6.1, timeout-1.4.2, cov-3.0.0
collecting ...
 airbyte-integrations/connectors/source-xero/unit_tests/test_incremental_streams.py::test_cursor_field ✓                                                                                       6% ▋
 airbyte-integrations/connectors/source-xero/unit_tests/test_incremental_streams.py::test_get_updated_state ✓                                                                                 11% █▎
 airbyte-integrations/connectors/source-xero/unit_tests/test_incremental_streams.py::test_stream_slices ✓                                                                                     17% █▋
 airbyte-integrations/connectors/source-xero/unit_tests/test_incremental_streams.py::test_supports_incremental ✓                                                                              22% ██▎
 airbyte-integrations/connectors/source-xero/unit_tests/test_incremental_streams.py::test_source_defined_cursor ✓                                                                             28% ██▊
 airbyte-integrations/connectors/source-xero/unit_tests/test_incremental_streams.py::test_stream_checkpoint_interval ✓                                                                        33% ███▍
 airbyte-integrations/connectors/source-xero/unit_tests/test_source.py::test_check_connection ✓                                                                                               39% ███▉
 airbyte-integrations/connectors/source-xero/unit_tests/test_source.py::test_streams ✓                                                                                                        44% ████▌
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_request_params ✓                                                                                                50% █████
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_next_page_token ✓                                                                                               56% █████▋
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_parse_response ✓                                                                                                61% ██████▎
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_request_headers ✓                                                                                               67% ██████▋
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_http_method ✓                                                                                                   72% ███████▎
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_should_retry[HTTPStatus.OK-False] ✓                                                                             78% ███████▊
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_should_retry[HTTPStatus.BAD_REQUEST-False] ✓                                                                    83% ████████▍
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_should_retry[HTTPStatus.TOO_MANY_REQUESTS-True] ✓                                                               89% ████████▉
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_should_retry[HTTPStatus.INTERNAL_SERVER_ERROR-True] ✓                                                           94% █████████▌
 airbyte-integrations/connectors/source-xero/unit_tests/test_streams.py::test_backoff_time ✓                                                                                                 100% ██████████

Results (0.81s):
      18 passed
Acceptance
============================= test session starts ==============================
platform darwin -- Python 3.9.12, pytest-6.1.2, py-1.11.0, pluggy-0.13.1 -- /Users/evgenyseleznev/Develop/airbyte-contest/airbyte-integrations/connectors/source-xero/.venv/bin/python
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('/Users/evgenyseleznev/Develop/airbyte-contest/airbyte-integrations/connectors/source-xero/.hypothesis/examples')
rootdir: /Users/evgenyseleznev/Develop/airbyte-contest, configfile: pytest.ini
plugins: hypothesis-6.54.6, sugar-0.9.5, requests-mock-1.9.3, mock-3.6.1, timeout-1.4.2, cov-3.0.0
collecting ... collected 29 items

../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_config_match_spec[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_match_expected[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_docker_env[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_oneof_usage[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_required[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_optional[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_has_secret[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_secret_never_in_the_output[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_defined_refs_exist_in_json_spec_file[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_oauth_flow_parameters[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_backward_compatibility[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestSpec::test_additional_properties_is_true[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestConnection::test_check[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestConnection::test_check[inputs1] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_discover[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_defined_cursors_exist_in_schema[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_defined_refs_exist_in_schema[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_defined_keyword_exist_in_schema[inputs0-allOf] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_defined_keyword_exist_in_schema[inputs0-not] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_primary_keys_exist_in_schema[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_streams_has_sync_modes[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_additional_properties_is_true[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestDiscovery::test_backward_compatibility[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestBasicRead::test_read[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_core.py::TestBasicRead::test_airbyte_trace_message_on_failure[inputs0] {"type": "LOG", "log": {"level": "ERROR", "message": "Docker container failed, code 1, error:\n{\"type\": \"TRACE\", \"trace\": {\"type\": \"ERROR\", \"emitted_at\": 1667149538632.529, \"error\": {\"message\": \"Something went wrong in the connector. See the logs for more details.\", \"internal_message\": \"2 validation errors for ConfiguredAirbyteCatalog\\nstreams -> 0 -> sync_mode\\n  value is not a valid enumeration member; permitted: 'full_refresh', 'incremental' (type=type_error.enum; enum_values=[<SyncMode.full_refresh: 'full_refresh'>, <SyncMode.incremental: 'incremental'>])\\nstreams -> 0 -> destination_sync_mode\\n  value is not a valid enumeration member; permitted: 'append', 'overwrite', 'append_dedup' (type=type_error.enum; enum_values=[<DestinationSyncMode.append: 'append'>, <DestinationSyncMode.overwrite: 'overwrite'>, <DestinationSyncMode.append_dedup: 'append_dedup'>])\", \"stack_trace\": \"Traceback (most recent call last):\\n  File \\\"/airbyte/integration_code/main.py\\\", line 13, in <module>\\n    launch(source, sys.argv[1:])\\n  File \\\"/usr/local/lib/python3.9/site-packages/airbyte_cdk/entrypoint.py\\\", line 131, in launch\\n    for message in source_entrypoint.run(parsed_args):\\n  File \\\"/usr/local/lib/python3.9/site-packages/airbyte_cdk/entrypoint.py\\\", line 119, in run\\n    config_catalog = self.source.read_catalog(parsed_args.catalog)\\n  File \\\"/usr/local/lib/python3.9/site-packages/airbyte_cdk/sources/source.py\\\", line 90, in read_catalog\\n    return ConfiguredAirbyteCatalog.parse_obj(self.read_config(catalog_path))\\n  File \\\"pydantic/main.py\\\", line 521, in pydantic.main.BaseModel.parse_obj\\n  File \\\"pydantic/main.py\\\", line 341, in pydantic.main.BaseModel.__init__\\npydantic.error_wrappers.ValidationError: 2 validation errors for ConfiguredAirbyteCatalog\\nstreams -> 0 -> sync_mode\\n  value is not a valid enumeration member; permitted: 'full_refresh', 'incremental' (type=type_error.enum; enum_values=[<SyncMode.full_refresh: 'full_refresh'>, <SyncMode.incremental: 'incremental'>])\\nstreams -> 0 -> destination_sync_mode\\n  value is not a valid enumeration member; permitted: 'append', 'overwrite', 'append_dedup' (type=type_error.enum; enum_values=[<DestinationSyncMode.append: 'append'>, <DestinationSyncMode.overwrite: 'overwrite'>, <DestinationSyncMode.append_dedup: 'append_dedup'>])\\n\", \"failure_type\": \"system_error\"}}}\n"}}
PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_full_refresh.py::TestFullRefresh::test_sequential_reads[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_incremental.py::TestIncremental::test_two_sequential_reads[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_incremental.py::TestIncremental::test_read_sequential_slices[inputs0] PASSED
../../bases/source-acceptance-test/source_acceptance_test/tests/test_incremental.py::TestIncremental::test_state_with_abnormally_large_values[inputs0] PASSED
{"type": "LOG", "log": {"level": "INFO", "message": "/Users/evgenyseleznev/Develop/airbyte-contest/airbyte-integrations/connectors/source-xero - SAT run - bf79acf00c3d45bf616b43901d8b79d6b73c2c59 - PASSED"}}


=============================== warnings summary ===============================
airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/tests/test_core.py: 24 warnings
airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/tests/test_full_refresh.py: 1 warning
airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/tests/test_incremental.py: 3 warnings
  /Users/evgenyseleznev/Develop/airbyte-contest/airbyte-integrations/connectors/source-xero/.venv/lib/python3.9/site-packages/docker/utils/utils.py:52: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
    s1 = StrictVersion(v1)

airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/tests/test_core.py: 24 warnings
airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/tests/test_full_refresh.py: 1 warning
airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/tests/test_incremental.py: 3 warnings
  /Users/evgenyseleznev/Develop/airbyte-contest/airbyte-integrations/connectors/source-xero/.venv/lib/python3.9/site-packages/docker/utils/utils.py:53: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
    s2 = StrictVersion(v2)

-- Docs: https://docs.pytest.org/en/stable/warnings.html
================= 29 passed, 56 warnings in 376.43s (0:06:16) ==================

@CLAassistant
Copy link

CLAassistant commented Oct 30, 2022

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added area/connectors Connector related issues area/documentation Improvements or additions to documentation labels Oct 30, 2022
@alkali alkali changed the title 🎉 New Source - Vantage 🎉 New Source - Xero Oct 30, 2022
Copy link
Member

@marcosmarxm marcosmarxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @alkali, Marcos from Airbyte here 👋 . We received more than 25 new contributions along the weekend. One is yours 🎉 thank so much for! Our team is limited and maybe the review process can take longer than expected. As described in the Airbyte's Hacktoberfest your contribution was submitted before November 2nd and it is eligible to win the prize. The review process will validate other requirements. I ask to you patience until someone from the team review it.

Because I reviewed some contributions for Hacktoberfest so far I saw some common patterns you can check in advance:

  • Make sure you have added connector documentation to /docs/integrations/
  • Remove the file catalog from /integration_tests
  • Edit the sample_config.json inside /integration_tests
  • For the configured_catalog you can use only json_schema: {}
  • Add title to all properties in the spec.yaml
  • Make sure the documentationUrl in the spec.yaml redirect to Airbyte's future connector page, eg: connector Airtable the documentationUrl: https://docs.airbyte.com/integrations/sources/airtable
  • Review now new line at EOF (end-of-file) for all files.

If possible send to me a DM in Slack with the tests credentials, this process will make easier to us run integration tests and publish your connector. If you only has production keys, make sure to create a bootstrap.md explaining how to get the keys.

@marcosmarxm marcosmarxm changed the title 🎉 New Source - Xero 🎉 New Source - Xero [python cdk] Oct 31, 2022
@marcosmarxm
Copy link
Member

@alkali can you sign the CLA?

@alkali
Copy link
Contributor Author

alkali commented Oct 31, 2022

@alkali can you sign the CLA?

yeah, I did it
image
dunno why the check didn't update

Copy link
Member

@marcosmarxm marcosmarxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment about custom function, @alkali do you have a test credential to share?

Comment on lines +16 to +48
def parse_date(value):
# Xero datetimes can be .NET JSON date strings which look like
# "/Date(1419937200000+0000)/"
# https://developer.xero.com/documentation/api/requests-and-responses
pattern = r"Date\((\-?\d+)([-+])?(\d+)?\)"
match = re.search(pattern, value)

iso8601pattern = r"((\d{4})-([0-2]\d)-0?([0-3]\d)T([0-5]\d):([0-5]\d):([0-6]\d))"

if not match:
iso8601match = re.search(iso8601pattern, value)
if iso8601match:
try:
return datetime.strptime(value)
except Exception:
return None
else:
return None

millis_timestamp, offset_sign, offset = match.groups()
if offset:
if offset_sign == "+":
offset_sign = 1
else:
offset_sign = -1
offset_hours = offset_sign * int(offset[:2])
offset_minutes = offset_sign * int(offset[2:])
else:
offset_hours = 0
offset_minutes = 0

return datetime.fromtimestamp((int(millis_timestamp) / 1000), tz=timezone.utc) + timedelta(hours=offset_hours, minutes=offset_minutes)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add unit test for this function, also looks this function doesn't two different things, maybe you can break into two.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it's not necessary to split these function in two as it's used for one certain thing: parse .NET JSON date format into datetime and these functions will never be used separately

I've added a unit test for this one, thanks for the catch

@alkali
Copy link
Contributor Author

alkali commented Oct 31, 2022

A comment about custom function, @alkali do you have a test credential to share?

added them on integration_tests/sample_config.json

logger = logging.getLogger("airbyte")


class XeroCustomCuonnectionsOauth2Authenticator(Oauth2Authenticator):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a typo here - XeroCustomCuonnectionsOauth2Authenticator

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alkali correct this and the connector is ready to go 🚀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@marcosmarxm marcosmarxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small correction and it is ready to publish!

logger = logging.getLogger("airbyte")


class XeroCustomCuonnectionsOauth2Authenticator(Oauth2Authenticator):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alkali correct this and the connector is ready to go 🚀


## Prerequisites

First of all you should create an application in [Xero development center](https://developer.xero.com/app/manage/). The only supported integration type is to use [Xero Custom Connections](https://developer.xero.com/documentation/guides/oauth2/custom-connections/developer) so you should choose it on creating your Xero App.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alkali could you provide some context as to why this requires a Xero Custom Connection?

That's quite a limitation for some use cases for this connector, I would imagine.

Would someone be able to pick this up and adapt your code so that it could work with some extra short-lived token / refresh token logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefl Xero access_token lives 30 minutes. Refresh_token lives 60 days, but if an application has used it for updating access_token, Xero will give you a new refresh_token and the old one will expire 30 minutes after usage. So it basically means that after refreshing access_token we should save a new refresh_token somewhere in the credentials (in the connector's config). This is impossible for now and I was waiting for #3990 to be resolved.

I have a workaround (I am actually using this Xero connector at my job for a while) - use an additional custom OAuth2Connector, which sends a callback with a new refresh_token to a particular URL, and some code at this particular URL updates the connector's config with new refresh_token. But I'm pretty sure this is not the way for a publicly released connector.

@marcosmarxm
Copy link
Member

marcosmarxm commented Nov 4, 2022

Hello! Your PR is approved but didn't have the time to publish and merge it this week. As you can check in Chris' comment all PRs submitted before 2-nov are eligible to win the prize. I'll be out of the office on Friday and return Monday to start publishing your contribution. Any question you can send a message in #hacktoberfest-2022 channel in Airbyte's Slack.

Have a good weekend and thank you for this amazing contribution for Hacktoberfest 🎉

@marcosmarxm
Copy link
Member

marcosmarxm commented Nov 9, 2022

/test connector=connectors/source-xero

🕑 connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3424535277
❌ connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3424535277
🐛 https://gradle.com/s/rce6p3wooqszs

Build Failed

Test summary info:

Could not find result summary

@marcosmarxm
Copy link
Member

marcosmarxm commented Nov 11, 2022

/test connector=connectors/source-xero

🕑 connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3447117812
❌ connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3447117812
🐛 https://gradle.com/s/ghmggu7fdqi2o

Build Failed

Test summary info:

Could not find result summary

@marcosmarxm
Copy link
Member

marcosmarxm commented Nov 11, 2022

/test connector=connectors/source-xero

🕑 connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3447238885
❌ connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3447238885
🐛 https://gradle.com/s/jqyjk4tmqlzec

Build Failed

Test summary info:

=========================== short test summary info ============================
FAILED test_incremental.py::TestIncremental::test_state_with_abnormally_large_values[inputs0]
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/source_acceptance_test/tests/test_core.py:65: The previous connector image could not be retrieved.
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/source_acceptance_test/tests/test_core.py:243: The previous connector image could not be retrieved.
======= 1 failed, 26 passed, 2 skipped, 29 warnings in 326.78s (0:05:26) =======

> Task :airbyte-integrations:connectors:source-xero:sourceAcceptanceTest FAILED

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.4/userguide/command_line_interface.html#sec:command_line_warnings

Execution optimizations have been disabled for 1 invalid unit(s) of work during this build to ensure correctness.
Please consult deprecation warnings for more details.
48 actionable tasks: 35 executed, 13 up-to-date

Publishing build scan...
https://gradle.com/s/jqyjk4tmqlzec

@marcosmarxm
Copy link
Member

marcosmarxm commented Nov 11, 2022

/test connector=connectors/source-xero

🕑 connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3447565268
✅ connectors/source-xero https://github.com/airbytehq/airbyte/actions/runs/3447565268
Python tests coverage:

Name                      Stmts   Miss  Cover
---------------------------------------------
source_xero/oauth.py         37      0   100%
source_xero/__init__.py       2      0   100%
source_xero/source.py        31      2    94%
source_xero/streams.py      155     22    86%
---------------------------------------------
TOTAL                       225     24    89%
	 Name                                                 Stmts   Miss  Cover   Missing
	 ----------------------------------------------------------------------------------
	 source_acceptance_test/base.py                          12      4    67%   16-19
	 source_acceptance_test/config.py                       139      5    96%   87, 93, 235, 239-240
	 source_acceptance_test/conftest.py                     196     92    53%   35, 41-43, 48, 54, 60, 66, 72-74, 93, 98-100, 106-108, 114-115, 120-121, 126, 132, 141-150, 156-161, 176, 200, 231, 237, 243-248, 256-261, 269-282, 287-293, 300-311, 318-334
	 source_acceptance_test/plugin.py                        69     25    64%   22-23, 31, 36, 120-140, 144-148
	 source_acceptance_test/tests/test_core.py              345    110    68%   53, 64-72, 77-84, 88-89, 93-94, 178, 216-233, 242-250, 254-259, 265, 298-303, 341-348, 391-393, 396, 461-469, 481-484, 489, 545-546, 552, 555, 591-601, 614-639
	 source_acceptance_test/tests/test_incremental.py       158     14    91%   52-59, 64-77, 240
	 source_acceptance_test/utils/asserts.py                 37      2    95%   57-58
	 source_acceptance_test/utils/common.py                  94     10    89%   16-17, 32-38, 72, 75
	 source_acceptance_test/utils/compare.py                 62     23    63%   21-51, 68, 97-99
	 source_acceptance_test/utils/connector_runner.py       112     50    55%   23-26, 32, 36, 39-68, 71-73, 76-78, 81-83, 86-88, 91-93, 96-114, 148-150
	 source_acceptance_test/utils/json_schema_helper.py     105     13    88%   30-31, 38, 41, 65-68, 96, 120, 190-192
	 ----------------------------------------------------------------------------------
	 TOTAL                                                 1508    348    77%

Build Passed

Test summary info:

=========================== short test summary info ============================
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/source_acceptance_test/tests/test_core.py:65: The previous connector image could not be retrieved.
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/source_acceptance_test/tests/test_core.py:243: The previous connector image could not be retrieved.
============ 27 passed, 2 skipped, 29 warnings in 319.72s (0:05:19) ============

@marcosmarxm
Copy link
Member

marcosmarxm commented Nov 11, 2022

/publish connector=connectors/source-xero

🕑 Publishing the following connectors:
connectors/source-xero
https://github.com/airbytehq/airbyte/actions/runs/3447650998


Connector Did it publish? Were definitions generated?
connectors/source-xero

if you have connectors that successfully published but failed definition generation, follow step 4 here ▶️

Copy link
Member

@marcosmarxm marcosmarxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @alkali

@marcosmarxm marcosmarxm merged commit 705dd3e into airbytehq:master Nov 11, 2022
@RealChrisSean RealChrisSean added the python Pull requests that update Python code label Nov 15, 2022
@RealChrisSean
Copy link

Hello @alkali can you please add your email to your github profile. This will allow us to contact you about your payout :).

If you don't want to make your email public, please DM me on slack with the following:

  • First and Last name
  • Email
  • link to this PR

Thanks!

@alkali
Copy link
Contributor Author

alkali commented Nov 18, 2022

@RealChrisSean added an email to the profile, thx for noticing

akashkulk pushed a commit that referenced this pull request Dec 2, 2022
* xero connector 0.1.0

* docs and stuff

* CR fixes: added sample_config.json and removed ununsed catalog.json

* CR fixes: added unit test for parse_date

* CR: typo fixed

* add xero to source def

* correct tests

* update accpt test

* correct abnormal state file

* auto-bump connector version

Co-authored-by: marcosmarxm <marcosmarxm@gmail.com>
Co-authored-by: Octavia Squidington III <octavia-squidington-iii@users.noreply.github.com>
Co-authored-by: Marcos Marx <marcosmarxm@users.noreply.github.com>
@sajarin sajarin added internal and removed bounty labels Dec 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/connectors Connector related issues area/documentation Improvements or additions to documentation community connectors/source/xero hacktober internal python Pull requests that update Python code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants