Skip to content

Commit 3facabf

Browse files
committed
Add CI, Contributing, and Security policies
1 parent 1bbd2d7 commit 3facabf

3 files changed

Lines changed: 239 additions & 46 deletions

File tree

.github/workflows/ci.yml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
MIX_ENV: test
11+
12+
jobs:
13+
format:
14+
name: Format check
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: erlef/setup-beam@v1
19+
with:
20+
elixir-version: "1.19.5"
21+
otp-version: "28.3"
22+
- name: Check formatting
23+
run: |
24+
for pkg in runcom runcom_ecto runcom_rmq runcom_web; do
25+
echo "==> Checking $pkg"
26+
(cd "$pkg" && mix format --check-formatted)
27+
done
28+
29+
test-pure:
30+
name: Test ${{ matrix.package }}
31+
runs-on: ubuntu-latest
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
package: [runcom, runcom_rmq]
36+
steps:
37+
- uses: actions/checkout@v4
38+
- uses: erlef/setup-beam@v1
39+
with:
40+
elixir-version: "1.19.5"
41+
otp-version: "28.3"
42+
- name: Cache deps
43+
uses: actions/cache@v4
44+
with:
45+
path: |
46+
${{ matrix.package }}/deps
47+
${{ matrix.package }}/_build
48+
key: ${{ runner.os }}-mix-${{ matrix.package }}-${{ hashFiles(format('{0}/mix.lock', matrix.package)) }}
49+
restore-keys: |
50+
${{ runner.os }}-mix-${{ matrix.package }}-
51+
- name: Install deps
52+
working-directory: ${{ matrix.package }}
53+
run: mix deps.get
54+
- name: Compile (warnings as errors)
55+
working-directory: ${{ matrix.package }}
56+
run: mix compile --warnings-as-errors
57+
- name: Check for compile-time dependency cycles
58+
working-directory: ${{ matrix.package }}
59+
run: mix xref graph --format cycles --fail-above 0
60+
- name: Run tests
61+
working-directory: ${{ matrix.package }}
62+
run: mix test
63+
64+
test-postgres:
65+
name: Test ${{ matrix.package }}
66+
runs-on: ubuntu-latest
67+
strategy:
68+
fail-fast: false
69+
matrix:
70+
package: [runcom_ecto, runcom_web]
71+
services:
72+
postgres:
73+
image: postgres:17-alpine
74+
env:
75+
POSTGRES_USER: postgres
76+
POSTGRES_PASSWORD: postgres
77+
POSTGRES_DB: postgres
78+
ports:
79+
- 5432:5432
80+
options: >-
81+
--health-cmd="pg_isready -U postgres"
82+
--health-interval=5s
83+
--health-timeout=5s
84+
--health-retries=5
85+
steps:
86+
- uses: actions/checkout@v4
87+
- uses: erlef/setup-beam@v1
88+
with:
89+
elixir-version: "1.19.5"
90+
otp-version: "28.3"
91+
- name: Cache deps
92+
uses: actions/cache@v4
93+
with:
94+
path: |
95+
${{ matrix.package }}/deps
96+
${{ matrix.package }}/_build
97+
key: ${{ runner.os }}-mix-${{ matrix.package }}-${{ hashFiles(format('{0}/mix.lock', matrix.package)) }}
98+
restore-keys: |
99+
${{ runner.os }}-mix-${{ matrix.package }}-
100+
- name: Install deps
101+
working-directory: ${{ matrix.package }}
102+
run: mix deps.get
103+
- name: Compile (warnings as errors)
104+
working-directory: ${{ matrix.package }}
105+
run: mix compile --warnings-as-errors
106+
- name: Check for compile-time dependency cycles
107+
working-directory: ${{ matrix.package }}
108+
run: mix xref graph --format cycles --fail-above 0
109+
- name: Run tests
110+
working-directory: ${{ matrix.package }}
111+
run: mix test

CONTRIBUTING.md

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,86 @@
11
# Contributing to Runcom
22

3-
Thanks for your interest in contributing! Runcom is a monorepo of Elixir
4-
packages for building and executing change plans with checkpointing.
3+
Thanks for your interest in contributing! This document explains how to get set up,
4+
what to expect, and how to submit changes.
55

6-
## Ground Rules
6+
## Code of Conduct
77

8-
- Be respectful — see the [Code of Conduct](CODE_OF_CONDUCT.md).
9-
- File an issue before opening a non-trivial PR so we can align on direction.
10-
- Keep PRs focused. One concern per PR makes review faster.
11-
- All contributions are licensed under Apache 2.0 (see [LICENSE](LICENSE)).
8+
This project adheres to the [Contributor Covenant](CODE_OF_CONDUCT.md). By
9+
participating, you are expected to uphold it. Please report unacceptable behavior
10+
to the maintainers.
1211

13-
## Monorepo Layout
12+
## Repository Layout
1413

15-
| Package | Purpose |
16-
|---------|---------|
17-
| `runcom/` | Core DSL, step behaviours, execution engine, checkpointing |
18-
| `runcom_ecto/` | Ecto/Postgres persistence |
19-
| `runcom_web/` | Phoenix LiveView dashboard |
20-
| `runcom_rmq/` | RabbitMQ transport via Broadway |
21-
| `runcom_demo/` | Demo app wiring everything together |
22-
| `runcom_demo_agent/` | Agent-side companion for distributed dispatch |
14+
Runcom is a monorepo of independently-published Hex packages:
2315

24-
Each package has its own `mix.exs`, `deps/`, and `_build/`. During local
16+
| Package | Path | Purpose |
17+
|---------|------|---------|
18+
| `runcom` | `runcom/` | Core DSL, step behaviours, execution engine, checkpointing |
19+
| `runcom_ecto` | `runcom_ecto/` | Ecto/Postgres persistence |
20+
| `runcom_web` | `runcom_web/` | Phoenix LiveView dashboard |
21+
| `runcom_rmq` | `runcom_rmq/` | RabbitMQ transport |
22+
| `runcom_demo` | `runcom_demo/` | Demo app wiring everything together |
23+
| `runcom_demo_agent` | `runcom_demo_agent/` | Agent-side companion for the demo |
24+
25+
Each package has its own `mix.exs`, `_build/`, and `deps/`. During local
2526
development, packages reference each other via path deps.
2627

2728
## Development Setup
2829

29-
Runtime versions are managed by [`mise`](https://mise.jdx.dev):
30-
31-
```bash
32-
mise install # installs Elixir 1.20-rc.2, OTP 28, Node 22
33-
```
30+
Runtime versions are managed by [mise](https://mise.jdx.dev) (see `mise.toml`):
3431

35-
Per-package workflow:
32+
- Elixir 1.20-rc.2
33+
- OTP 28
34+
- Node 22
3635

3736
```bash
38-
cd runcom # (or any package)
39-
mix deps.get
40-
mix compile
37+
# Per-package (run from package directory)
38+
mix deps.get && mix compile
4139
mix test
4240
mix format
41+
42+
# Full demo stack
43+
cd runcom_demo && docker compose up
4344
```
4445

45-
Full demo stack (Postgres + RabbitMQ + MinIO + agents):
46+
## Making Changes
4647

47-
```bash
48-
cd runcom_demo
49-
docker compose up
50-
```
48+
1. **Fork and branch** — create a feature branch from `main`.
49+
2. **Write tests** — all new behavior should be covered by tests. For Elixir
50+
code, async tests are preferred; avoid global state.
51+
3. **Format** — run `mix format` before committing.
52+
4. **Keep changes focused** — one logical change per PR. Unrelated cleanups
53+
should go in separate PRs.
54+
5. **Update docs** — if you change public APIs, update the module `@doc` and
55+
relevant README sections.
56+
57+
## Commit Messages
58+
59+
Use present-tense imperative subjects ("Add checkpoint resume", not "Added" or
60+
"Adds"). Reference issues in the body when applicable.
61+
62+
## Pull Requests
63+
64+
When opening a PR:
65+
66+
- Describe *what* changed and *why* — link to any relevant issue or discussion.
67+
- Include test output or screenshots where relevant.
68+
- Expect review feedback; we aim to respond within a few business days.
5169

52-
## Submitting Changes
70+
## Reporting Bugs
5371

54-
1. Fork and create a feature branch from `main`.
55-
2. Make your changes with tests.
56-
3. Run `mix format` and `mix test` in every package you touched.
57-
4. Open a PR with a clear description of the change and its motivation.
72+
Open an issue with:
5873

59-
## Reporting Issues
74+
- A minimal reproduction (ideally a failing test or runbook snippet).
75+
- Elixir/OTP versions (`elixir --version`).
76+
- Relevant logs or stack traces.
6077

61-
Please include:
78+
## Security Issues
6279

63-
- Which package(s) are affected
64-
- Elixir/OTP versions (`elixir --version`)
65-
- A minimal reproduction if possible
66-
- Relevant log output
80+
Do **not** open a public issue for security vulnerabilities. See the security
81+
policy (if present) or email the maintainers directly.
6782

68-
## Security
83+
## License
6984

70-
Please do **not** file public issues for security vulnerabilities. Instead,
71-
email the maintainers at the address listed in the package `mix.exs` or
72-
contact us privately via GitHub.
85+
By contributing, you agree that your contributions will be licensed under the
86+
[Apache License 2.0](LICENSE).

SECURITY.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
Runcom is a multi-package monorepo. Security fixes are applied to the latest
6+
released minor version of each package on Hex:
7+
8+
- `runcom`
9+
- `runcom_ecto`
10+
- `runcom_rmq`
11+
- `runcom_web`
12+
13+
Older versions are not patched. Please upgrade to the latest release before
14+
reporting.
15+
16+
## Reporting a Vulnerability
17+
18+
**Do not open a public GitHub issue for security vulnerabilities.**
19+
20+
Please report suspected vulnerabilities using GitHub's private vulnerability
21+
reporting:
22+
23+
https://github.com/tv-labs/runcom/security/advisories/new
24+
25+
Include as much of the following as you can:
26+
27+
- A description of the vulnerability and its impact
28+
- Which package(s) and version(s) are affected
29+
- Steps to reproduce (a minimal runbook or test case is ideal)
30+
- Any known mitigations or workarounds
31+
32+
We aim to acknowledge reports within 3 business days and to provide an initial
33+
assessment within 7 business days. Coordinated disclosure timelines are agreed
34+
with the reporter on a case-by-case basis, typically within 90 days of the
35+
initial report.
36+
37+
## Scope
38+
39+
The following are in scope for reports:
40+
41+
- Signature forgery, replay, or bypass in `RuncomRmq.Codec`
42+
- Deserialization issues reachable without a valid HMAC signature
43+
- Authentication or authorization bypasses in `runcom_web`
44+
- SQL injection, path traversal, or command injection in any package
45+
- Secret leakage via logs, telemetry, or the dashboard
46+
- Checkpoint or dispatch-state tampering that leads to unintended execution
47+
48+
The following are generally **out of scope**:
49+
50+
- Issues that require an already-compromised signing secret, database, or
51+
RabbitMQ broker (the trust model assumes these are protected)
52+
- Denial of service from an authenticated, trusted agent
53+
- Vulnerabilities in third-party dependencies — please report those upstream;
54+
if you believe Runcom's usage pattern amplifies the issue, include that
55+
reasoning
56+
57+
## Deployment Guidance
58+
59+
When deploying Runcom, please review:
60+
61+
- The [Security section](README.md#security) of the root README for message
62+
signing requirements
63+
- The [key rotation guide](runcom_rmq/README.md#key-rotation) in `runcom_rmq`
64+
for rotating signing secrets without downtime
65+
- Ensure `RUNCOM_SIGNING_SECRET` is at least 32 random bytes and is not the
66+
demo value shipped in `docker-compose.yml`
67+
- Enable TLS on AMQP connections when RabbitMQ is reachable from untrusted
68+
networks

0 commit comments

Comments
 (0)