Thank you for your interest in Singularity.Workflow! This document provides guidelines for contributing to the project.
- Elixir 1.14+
- PostgreSQL 14+
- Mix (comes with Elixir)
- Clone the repository:
git clone https://github.com/mikkihugo/singularity_workflow.git
cd singularity_workflow- Install dependencies:
mix deps.get- Set up the database:
# Create test database
createdb singularity_workflow_test
# Configure connection
export DATABASE_URL="postgres://localhost/singularity_workflow_test"
# Run migrations
mix ecto.migrate- Run tests to verify setup:
mix test# Run all tests
mix test
# Run specific test file
mix test test/singularity_workflow/executor_test.exs
# Run tests with coverage report
mix test.coverage
# Run tests in watch mode (auto-rerun on file changes)
mix test.watchSingularity.Workflow enforces high code quality standards:
# Run all quality checks (recommended before committing)
mix quality
# Individual checks:
mix format # Format code
mix credo --strict # Linting (shows code smells)
mix dialyzer # Type checking
mix sobelow --exit-on-warning # Security analysis
mix deps.audit # Check dependencies for vulnerabilitiesSingularity.Workflow follows standard Elixir conventions:
- Formatting: Run
mix formatbefore committing - Line Length: Maximum 100 characters (enforced in .formatter.exs)
- Naming: Use descriptive names, avoid abbreviations
- Modules: One module per file, named after the file
- Documentation: All public modules and functions require @moduledoc/@doc
All code contributions must include:
-
Module Documentation (@moduledoc)
defmodule Singularity.Workflow.MyModule do @moduledoc """ Brief description of what this module does. ## Examples iex> MyModule.my_function("input") "output" """
-
Function Documentation (@doc)
@doc """ Description of what the function does. ## Parameters - param1: description ## Returns - ok tuple with result - error tuple with reason ## Examples iex> my_function("value") {:ok, "result"} """ @spec my_function(String.t()) :: {:ok, String.t()} | {:error, term()} def my_function(input) do {:ok, input} end
-
Type Specifications (@spec)
- Always include @spec for public functions
- Use accurate types (not just any)
-
Inline Comments for complex logic
- Explain why not what (code shows what)
- Describe algorithms and performance implications
- Note edge cases and gotchas
Singularity.Workflow uses PostgreSQL as the source of truth. When adding features:
- Schema Changes: Create migrations for all schema additions
- SQL Functions: Complex logic lives in PostgreSQL functions (for atomicity)
- Transactions: Use Ecto's transaction API for multi-statement operations
- Indexes: Add indexes for columns used in WHERE clauses frequently
When working with workflows:
- Acyclic: Ensure dependency graphs remain acyclic
- Deterministic: Same input should produce same execution plan
- Observable: All state changes must be queryable from database
- Recoverable: System must survive process crashes
-
Create a test that reproduces the bug:
describe "bug behavior" do test "should work correctly" do # Reproduce the bug {:error, _} = function_call() end end
-
Make the minimum change to fix it
-
Verify the test now passes
-
Run
mix qualitybefore committing
- Open an issue first to discuss the feature
- Create a test for the feature
- Implement the feature
- Document the feature (code comments + docs)
- Update changelog with the feature
singularity_workflow/
├── lib/singularity_workflow/
│ ├── executor.ex # Main entry point
│ ├── flow_builder.ex # Dynamic workflow API
│ ├── repo.ex # Ecto repository
│ ├── dag/ # DAG-related modules
│ │ ├── workflow_definition.ex
│ │ ├── run_initializer.ex
│ │ ├── task_executor.ex
│ │ └── dynamic_workflow_loader.ex
│ ├── step_*.ex # Step-related schemas
│ └── workflow_run.ex # Workflow run schema
├── priv/repo/
│ └── migrations/ # Database migrations
├── test/
│ ├── singularity_workflow/
│ │ └── *_test.exs # Unit/integration tests
│ └── support/
│ └── sql_case.ex # Test helpers
├── CHANGELOG.md # Version history
├── docs/ARCHITECTURE.md # Technical deep dive
├── GETTING_STARTED.md # User guide
├── CONTRIBUTING.md # This file
└── mix.exs # Project definition
- Test individual functions
- Mock external dependencies (pgmq, workflows)
- Use ExUnit.Case + Mox for mocking
- Test full workflow execution end-to-end
- Use real PostgreSQL (test transaction isolation)
- Verify database state changes
defmodule Singularity.Workflow.MyModuleTest do
use ExUnit.Case
alias Singularity.Workflow.MyModule
describe "my_function/1" do
test "handles valid input" do
{:ok, result} = MyModule.my_function("input")
assert result == "expected"
end
test "returns error for invalid input" do
{:error, reason} = MyModule.my_function(nil)
assert reason == :invalid_input
end
end
endWrite clear, descriptive commit messages:
[type]: Brief description
Longer explanation of the change, why it was needed, and how it works.
- Use bullet points for multiple changes
- Reference issues: "Fixes #123"
- Keep first line under 50 characters
feat: New featurefix: Bug fixdocs: Documentation changesrefactor: Code reorganizationtest: Test additions/improvementsperf: Performance improvementschore: Build, dependencies, etc.
-
Create a feature branch:
git checkout -b feature/my-feature
-
Make your changes with clear commits
-
Run tests and quality checks:
mix quality mix test -
Push to GitHub and create a Pull Request:
git push origin feature/my-feature
-
PR Description should include:
- What problem does this solve?
- How does it solve the problem?
- Any breaking changes?
- Testing notes
-
Respond to feedback on code review
-
Maintainers will merge after approval
When reporting bugs, include:
- Description: What did you expect vs. what happened?
- Reproduction Steps: How to reproduce the bug
- Environment: Elixir version, PostgreSQL version, etc.
- Error Messages: Full stack traces if available
- Minimal Code Example: Smallest possible reproduction
All contributions go through code review:
- Correctness: Does the code do what it claims?
- Quality: Is the code maintainable and performant?
- Testing: Are there adequate tests?
- Documentation: Is it documented for users?
- Compatibility: Does it maintain backward compatibility?
Reviewers may request changes. Please:
- Don't take feedback personally
- Ask for clarification if needed
- Update your PR based on feedback
- Re-request review after changes
Singularity.Workflow follows Semantic Versioning:
- 0.1.0 (current): Initial release, API may change
- 0.x.0: Minor versions (new features, API additions)
- 1.0.0: First stable release (stable API)
- 1.x.0: Subsequent releases
Only maintainers can publish releases:
- Update version in
mix.exs - Update
CHANGELOG.md - Commit with message: "Release v0.x.0"
- Tag commit:
git tag v0.x.0 - Push tags:
git push --tags - Publish:
mix hex.publish
- General questions: Check GETTING_STARTED.md
- Architecture questions: See ARCHITECTURE.md
- Issue or PR: Open a GitHub issue
Thank you for contributing to Singularity.Workflow!