feat: open-source readiness — Apache 2.0, ETL refactor, CI scaffolding#1
Merged
Conversation
- Switch license from MIT to Apache 2.0 (aligns with dlt, Airflow, Spark ecosystem) - Add NOTICE file (Apache 2.0 §4(d)) - Add CONTRIBUTING.md, CODE_OF_CONDUCT.md (Contributor Covenant 2.1), SECURITY.md - Add .github/ scaffolding: tests workflow (Py 3.11/3.12/3.13), issue templates, PR template - pyproject.toml: project.urls, expanded classifiers, etl keyword - Scrub bc-cli references in README, CLAUDE.md, docs/contributing.md (repo is 'bcli') - Add shields to README (CI, license, Python versions) - Add ETL pipeline section to README
The ETL module now has a clean separation between reusable dlt-source logic and bcli-specific integration: - _generic.py: business_central() factory, EntityDef — no bcli imports - _client.py: minimal httpx + AuthProvider-based BC client - _auth.py: AuthProvider protocol + ClientCredentialsAuth + StaticTokenAuth - _stampers.py: fivetran_stamper, audit_stamper, company_id_stamper - _bridge.py: bcli_profile() — the ONLY module importing bcli.* The generic layer now works with any BC tenant via explicit credentials + entity list. The bridge wraps it to reuse bcli profiles and custom-API registries, with Fivetran-parity defaults (multi-company on, Fivetran audit columns on). CLI behavior unchanged: `bcli etl sync` still works the same way. Public API: from bcli.etl import business_central, EntityDef, fivetran_stamper from bcli.etl import bcli_profile # the bridge Test coverage restructured into test_generic.py (layer isolation including an AST-based import-rule guard), test_bridge.py, test_stampers.py. Synthetic tests/fixtures/sample_postman_collection.json replaces a developer-local Postman file for CI-portable importer tests.
Apply `ruff check --fix` cleanup in prep for CI lint gate: - Remove unused imports - Remove redundant f-string prefixes on literals - Remove unused local variables in tests No behavior changes.
|
You have used all of your free Bugbot PR reviews. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
The original workflow had two issues: 1. `uv python install` downloads an interpreter but doesn't activate it — uv fell back to the runner's system Python (3.12.3) regardless of matrix. 2. `uv pip install --system` on Ubuntu's externally-managed Python hits PEP 668 and refuses to install. Fix by passing `python-version` to setup-uv (it activates the matrix version) and installing into a venv via `uv pip install`.
setup-uv@v5 already creates and activates a .venv when python-version is passed, so the explicit `uv venv` step collides. `uv pip install -e` then installs directly into the activated venv.
igor-ctrl
added a commit
that referenced
this pull request
Apr 29, 2026
…context Fixes the #1 pain point when Claude Code uses bcli: -f/--format now works directly on get/post/patch/delete commands (not just as a global flag). New commands: - `bcli endpoint fields <name>` — fetches one record and prints field names with inferred types. Makes OData filter construction trivial for LLMs. - `bcli ai-context` — dumps markdown usage instructions for CLAUDE.md. Covers flag syntax, OData filters, common patterns, endpoint discovery. Bug fixes (found by Codex review): - `--top 0` and `--skip 0` no longer silently ignored (was truthy check) Other: - Help text on `get` command now shows examples with correct syntax - Auto-quiet when local --format is machine-readable (json/csv/ndjson/raw)
igor-ctrl
added a commit
that referenced
this pull request
Apr 29, 2026
feat: open-source readiness — Apache 2.0, ETL refactor, CI scaffolding
igor-ctrl
added a commit
that referenced
this pull request
May 4, 2026
…context Fixes the #1 pain point when Claude Code uses bcli: -f/--format now works directly on get/post/patch/delete commands (not just as a global flag). New commands: - `bcli endpoint fields <name>` — fetches one record and prints field names with inferred types. Makes OData filter construction trivial for LLMs. - `bcli ai-context` — dumps markdown usage instructions for CLAUDE.md. Covers flag syntax, OData filters, common patterns, endpoint discovery. Bug fixes (found by Codex review): - `--top 0` and `--skip 0` no longer silently ignored (was truthy check) Other: - Help text on `get` command now shows examples with correct syntax - Auto-quiet when local --format is machine-readable (json/csv/ndjson/raw)
igor-ctrl
added a commit
that referenced
this pull request
May 4, 2026
feat: open-source readiness — Apache 2.0, ETL refactor, CI scaffolding
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Prepares the repo for public release. Bundles three threads of work:
What changed
License (chore: prepare repo for open-source release)
LICENSE: MIT → Apache 2.0 (official text from apache.org)NOTICEadded (required by Apache 2.0 §4(d))pyproject.toml:license = \"Apache-2.0\", classifier updated,project.urlsaddedCONTRIBUTING.md,CODE_OF_CONDUCT.md(Contributor Covenant 2.1),SECURITY.mdat root.github/:workflows/tests.yml— pytest + ruff across Python 3.11/3.12/3.13ISSUE_TEMPLATE/bug_report.md+feature_request.mdPULL_REQUEST_TEMPLATE.mdbc-clireferences from README, CLAUDE.md, docsETL refactor (refactor: split bcli.etl into generic + bridge layers)
Before:
src/bcli/etl/_source.pymixed generic dlt logic with bcli-specific defaults (registry dependency, always-on multi-company, always-on Fivetran stamping).After:
```
src/bcli/etl/
├── _generic.py # business_central() factory, EntityDef — NO bcli imports
├── _client.py # minimal httpx + AuthProvider-based BC client
├── _auth.py # AuthProvider protocol + ClientCredentialsAuth + StaticTokenAuth
├── _stampers.py # fivetran_stamper, audit_stamper, company_id_stamper
└── _bridge.py # bcli_profile() — ONLY module importing bcli.*
```
The generic layer works with any BC tenant via explicit credentials + entity list:
```python
from bcli.etl import business_central, EntityDef, fivetran_stamper
source = business_central(
tenant_id="...", client_id="...", client_secret="...",
environment="Production",
entities=[EntityDef(name="customers")],
multi_company=True,
stampers=[fivetran_stamper()],
)
```
The bridge preserves today's Fivetran-parity defaults:
```python
from bcli.etl import bcli_profile
source = bcli_profile(profile="prod") # multi_company=True, fivetran_compat=True
```
Key design constraint: an AST-based test in
tests/test_etl/test_generic.pyfails the build if any generic-layer module imports frombcli.registry,bcli.client,bcli.config,bcli.auth, orbcli.errors.Style (style: ruff auto-fixes)
Routine cleanup across
src/andtests/— unused imports, redundant f-string prefixes, unused locals. No behavior changes.CLI unchanged
`bcli etl sync` works exactly the same; the cron job on the server keeps producing identical output. The bridge preserves multi-company + Fivetran audit columns by default.
Stats
39 files changed, +1811 / −695
Test plan
Follow-ups (out of scope for this PR)