Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 200 additions & 0 deletions airbyte-integrations/connectors/source-float/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,90 @@ definitions:
type: InlineSchemaLoader
schema:
$ref: "#/schemas/logged-time"
reports-people:
type: DeclarativeStream
name: reports-people
primary_key:
- people_id
retriever:
type: SimpleRetriever
requester:
$ref: "#/definitions/base_requester"
path: /reports/people
http_method: GET
request_parameters:
start_date: "{{ config['start_date'][:10] }}"
end_date: "{{ config.get('end_date', now_utc().strftime('%Y-%m-%d')) }}"
record_selector:
type: RecordSelector
extractor:
type: DpathExtractor
field_path:
- people
paginator:
type: NoPagination
decoder:
type: JsonDecoder
transformations:
# Report rows are a single aggregate per person for the whole requested
# range and carry no marker of the period they cover. Stamp the requested
# range onto each record so the numbers stay interpretable after the sync.
- type: AddFields
fields:
- type: AddedFieldDefinition
path:
- start_date
value: "{{ config['start_date'][:10] }}"
- type: AddedFieldDefinition
path:
- end_date
value: "{{ config.get('end_date', now_utc().strftime('%Y-%m-%d')) }}"
schema_loader:
type: InlineSchemaLoader
schema:
$ref: "#/schemas/reports-people"
reports-projects:
type: DeclarativeStream
name: reports-projects
primary_key:
- project_id
retriever:
type: SimpleRetriever
requester:
$ref: "#/definitions/base_requester"
path: /reports/projects
http_method: GET
request_parameters:
start_date: "{{ config['start_date'][:10] }}"
end_date: "{{ config.get('end_date', now_utc().strftime('%Y-%m-%d')) }}"
record_selector:
type: RecordSelector
extractor:
type: DpathExtractor
field_path:
- projects
paginator:
type: NoPagination
decoder:
type: JsonDecoder
transformations:
# Report rows are a single aggregate per project for the whole requested
# range and carry no marker of the period they cover. Stamp the requested
# range onto each record so the numbers stay interpretable after the sync.
- type: AddFields
fields:
- type: AddedFieldDefinition
path:
- start_date
value: "{{ config['start_date'][:10] }}"
- type: AddedFieldDefinition
path:
- end_date
value: "{{ config.get('end_date', now_utc().strftime('%Y-%m-%d')) }}"
schema_loader:
type: InlineSchemaLoader
schema:
$ref: "#/schemas/reports-projects"
base_requester:
type: HttpRequester
url_base: https://api.float.com/v3
Expand All @@ -650,6 +734,8 @@ streams:
- $ref: "#/definitions/streams/milestones"
- $ref: "#/definitions/streams/tasks"
- $ref: "#/definitions/streams/logged-time"
- $ref: "#/definitions/streams/reports-people"
- $ref: "#/definitions/streams/reports-projects"

spec:
type: Spec
Expand All @@ -673,6 +759,16 @@ spec:
title: Start date
format: date-time
pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$
end_date:
type: string
order: 2
title: End date
description: >-
End date for reports streams (YYYY-MM-DD). Defaults to today if not set.
Does not affect non-report streams.
pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$
examples:
- "2024-12-31"
additionalProperties: true

metadata:
Expand All @@ -693,6 +789,8 @@ metadata:
milestones: true
tasks: true
logged-time: true
reports-people: true
reports-projects: true
testedStreams:
accounts:
streamHash: 61b4653fec77bfd43c4d32853b39b293339fd2dd
Expand Down Expand Up @@ -1644,3 +1742,105 @@ schemas:
required:
- logged_time_id
- modified
reports-people:
type: object
$schema: http://json-schema.org/schema#
additionalProperties: true
properties:
people_id:
type:
- integer
- "null"
name:
type:
- string
- "null"
department_id:
type:
- integer
- "null"
department:
type:
- string
- "null"
people_type_id:
type:
- integer
- "null"
wk_day_hrs:
type:
- object
- "null"
capacity:
type:
- number
- "null"
timeoff:
type:
- number
- "null"
scheduled:
type:
- number
- "null"
billable:
type:
- number
- "null"
nonBillable:
type:
- number
- "null"
overtime:
type:
- number
- "null"
unscheduled:
type:
- number
- "null"
start_date:
type:
- string
- "null"
end_date:
type:
- string
- "null"
reports-projects:
type: object
$schema: http://json-schema.org/schema#
additionalProperties: true
properties:
project_id:
type:
- integer
- "null"
name:
type:
- string
- "null"
client_id:
type:
- integer
- "null"
scheduled:
type:
- number
- "null"
billable:
type:
- number
- "null"
nonBillable:
type:
- number
- "null"
start_date:
type:
- string
- "null"
end_date:
type:
- string
- "null"
2 changes: 1 addition & 1 deletion airbyte-integrations/connectors/source-float/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: 4f755eb9-6e1a-4b0e-bc1e-26b9f5d3ca4c
dockerImageTag: 0.0.56
dockerImageTag: 0.1.0
dockerRepository: airbyte/source-float
githubIssueLabel: source-float
icon: icon.svg
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) 2026 Airbyte, Inc., all rights reserved.

import os
from pathlib import Path

from airbyte_cdk.sources.declarative.yaml_declarative_source import YamlDeclarativeSource
from airbyte_cdk.test.catalog_builder import CatalogBuilder
from airbyte_cdk.test.state_builder import StateBuilder


pytest_plugins = ["airbyte_cdk.test.utils.manifest_only_fixtures"]

os.environ.setdefault("REQUEST_CACHE_PATH", "REQUEST_CACHE_PATH")


def _get_manifest_path() -> Path:
"""Find the connector directory holding manifest.yaml.

In CI (Docker): /airbyte/integration_code/source_declarative_manifest
Locally: the connector root, one level above unit_tests/
"""
ci_path = Path("/airbyte/integration_code/source_declarative_manifest")
if ci_path.exists():
return ci_path
# .resolve() because __file__ may be relative in CI.
return Path(__file__).resolve().parent.parent


MANIFEST_PATH = _get_manifest_path() / "manifest.yaml"


def get_source(config, state=None) -> YamlDeclarativeSource:
"""Build the declarative source under test from the connector's manifest.yaml."""
return YamlDeclarativeSource(
path_to_yaml=str(MANIFEST_PATH),
catalog=CatalogBuilder().build(),
config=config,
state=state or StateBuilder().build(),
)
Loading
Loading