Contributing

Thanks for contributing! Here's how to get started:

  1. Open an issue to discuss the proposed change
  2. Fork the repo and create a branch from main
  3. Implement the change with tests
  4. Make sure bundle exec fluence-ci all passes
  5. Open a pull request targeting main

Setup

git clone git@github.com:fluence-eu/mosaic-sdk.git
cd mosaic-sdk
bin/setup

Requires Ruby 3.2+.

Development

Running tests and linting

bundle exec fluence-ci all      # full catalog (lint + security + codequality + tests)
bundle exec fluence-ci lint     # rubocop only
bundle exec fluence-ci tests    # minitest only (auto-detected from test/test_helper.rb)
bundle exec rubocop -a          # auto-fix linting (no fluence-ci equivalent)

Interactive console

APPCENTER_CLIENT_ID=your_id APPCENTER_CLIENT_SECRET=your_secret bin/console

Commit Convention

This project follows Conventional Commits.

Format

<type>(<scope>): <description>

[body]

[footer(s)]

Types

Type Description
feat New feature
fix Bug fix
docs Documentation only changes
style Formatting changes (whitespace, commas, etc.) — no logic
refactor Code change that neither fixes a bug nor adds a feature
perf Performance improvement
test Adding or updating tests
build Changes to build system or dependencies
ci CI/CD configuration changes
chore Other changes that don't modify source or tests
revert Revert a previous commit

Scope

Optional — indicates the area of the project affected:

  • feat(clone): add create method
  • fix(nav): fix parameter mapping in create
  • refactor(base): extract build_instance logic

Description

  • Imperative mood ("add", not "adds" or "added")
  • No capital letter at the start
  • No period at the end
  • Maximum 72 characters

Body (optional)

  • Use bullet points with - for multiple items
  • Explain why, not what (the diff speaks for itself)

Breaking Changes

Non-backward-compatible changes must be flagged with:

  • A ! after the type/scope: feat(nav)!: change create parameters
  • And/or a BREAKING CHANGE: footer in the body

Examples

feat(clone): add create method
fix(nav): fix parameter mapping in create

- unit was not mapped to market_price_kind
- pricing_method was not mapped to market_price_type
refactor(base): extract CSV parsing logic

Move parsing functions into a dedicated concern
to improve reusability across services.
feat(nav)!: change create parameters

BREAKING CHANGE: pricing_method replaces the old type parameter,
clients must update their calls.

Branching Model

  • main — default branch. All feature branches are created from here, and all PRs target this branch.
  • Never push directly to main — always create a feature branch and open a PR.

Pull Request Convention

PR Title

  • Same format as commits: <type>(<scope>): <description>
  • Under 72 characters

PR Classification

Level Criteria Description requirements
Critical Breaking change, security fix, data migration Full description — summary, changes, impact, rollback plan, how to test
Major New feature, new endpoint, significant refactor Summary + changes + how to test
Minor Small bug fix, config tweak, dependency bump Summary + changes (1-2 lines each)
Trivial Documentation, formatting, comment update One-line summary is enough

PR Description by Level

Critical / Major

## Summary
<What and why in 2-3 sentences>

## Changes
- <change 1>
- <change 2>

## How to Test
1. <step 1>
2. <step 2>

For Critical PRs, also add:

## Impact
- <what parts of the system are affected>

## Rollback Plan
- <how to safely revert if something goes wrong>

Minor

## Summary
<One sentence>

## Changes
- <change 1>

Trivial

A one-line summary in the PR body is sufficient.

Rules

  • One topic per PR — don't mix unrelated changes
  • All tests must pass (bundle exec fluence-ci all)
  • New code must include tests
  • Never commit secrets or credentials

Architecture

lib/mosaic/sdk/
  models/
    base.rb          # Abstract class: list, create, associations, lazy loading
    bank.rb
    dna.rb
    clone.rb
    nav.rb
  client.rb          # HTTP client (get, post, put, patch, delete)
  configuration.rb   # SDK configuration (client_id, client_secret, base_url)
  version.rb
  • Base provides list and create — models can override create with NotImplementedError to disable it
  • Base::Instance handles lazy loading and chainable associations via self.association
  • Association chain: Dna -> Clone -> Nav
  • Context propagated via @extra hash (e.g. dna_id, clone_id)

Tests

  • Framework: Minitest (test/**/test_*.rb)
  • HTTP stubs via ClientStub in test/test_helper.rb — no real HTTP requests
  • Minimum coverage: 95% overall, 70% per file
  • All new code must be tested
  • Coverage checked on PRs via undercover (diff-based)

Code Conventions

  • frozen_string_literal: true on every Ruby file
  • Strings: single quotes (unless interpolation is needed)
  • RuboCop: no rule disabling without justification
  • Version in lib/mosaic/sdk/version.rb — do not modify unless for an explicit release
  • YARD-style doc comments on all public methods

CI

GitHub Actions:

  • main.yml — runs on every PR: RuboCop + Minitest + coverage check
  • release.yml — version bump and changelog generation (workflow_dispatch)
  • github-release.yml — creates GitHub releases from tags
  • publish.yml — publishes the gem to GitHub Packages

AI-Assisted Contributions

When using AI tools (Claude, Copilot, etc.) to generate commits or PRs:

  • Classify first — determine if the change is critical, major, minor, or trivial
  • Focus on the "why" — the diff already shows the "what"
  • Skip boilerplate — don't add empty sections or placeholder text

The person opening the PR takes full responsibility for the code. Before submitting:

  • [ ] I have read and understood every line of code in this PR
  • [ ] I can explain why each change was made
  • [ ] I have tested the changes locally

Do not add AI co-author lines (Co-Authored-By), "Generated with" footers, or any AI attribution in commits or PR descriptions.


License

By contributing, you agree that your contributions will be licensed under the MIT License.