Metadata-Version: 2.4
Name: gitopsctr
Version: 0.1.0
Summary: A local-first GitOps deployment reconciler.
Project-URL: Repository, https://github.com/NiklasRosenstein/gitopsctr
Author: Niklas Rosenstein
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# gitopsctr

`gitopsctr` is a local-first deployment reconciler. It materializes desired state from a source
revision, records deployment receipts in Git, promotes clean desired state between environments,
and creates forward-only rollback commits.

The command line is the complete operational interface. CI workflows and the reusable GitHub Action
invoke the same commands that an operator can run locally.

## Development

Requirements are managed with [mise](https://mise.jdx.dev/) and [uv](https://docs.astral.sh/uv/).

```console
mise install
mise run sync
mise run check
```

The project supports Python 3.12 and newer. Ruff formats and lints the code with a 120-character line
length; ty checks the package.

## CLI

Run `gitopsctr --help` for the complete command list. The CLI discovers the Git repository containing
the current directory. Use `--repository PATH` or `GITOPSCTR_REPOSITORY` to select one explicitly.

Important commands include:

- `advance-desired`: materialize the next desired-state commit.
- `reconcile`: run one unit's driver and publish its receipt.
- `converge`: reconcile a dependency closure locally.
- `promote`: promote a clean environment through its configured change gate.
- `rollback`: publish a forward desired-state commit from historical state.
- `verify`: ask supported drivers to check external state without writing receipts.

## Driver plugins

Drivers are discovered from the `gitopsctr.drivers` Python entry-point group. An entry point must load
an instance of `gitopsctr.driver.Driver`. Optional controller operations are declared through independent
capability base classes such as `VerificationCapability`. The drivers distributed in this package use the
same public registry and live under `gitopsctr.contrib.driver`.

## GitHub Action

The repository's root composite action wraps reconciliation preparation, `reconcile`, `advance-desired`, `promote`,
and `rollback`. `operation: prepare` is action-only orchestration terminology: it selects an exact desired revision
by calling `advance-desired` for a supplied source revision or `resolve-desired` otherwise. It does not add a
CLI command or persisted controller state. The action can
install the CLI from PyPI, from the checked-out action revision, or from an explicit Git repository
and revision. Caller workflows retain responsibility for credentials, deployment tools, permissions,
concurrency, and follow-up scheduling.

Prepare one exact desired revision before fan-out reconciliation jobs:

```yaml
- id: prepare
  uses: NiklasRosenstein/gitopsctr@<commit-or-ref>
  with:
    operation: prepare
    package-source: action
    environment: dev
    source-revision: ${{ github.sha }}
    require-source-ref: main
```

The outputs are `active`, `desired-revision`, `desired-changed`, and `advance-after-reconcile`. Supplying an
exact `desired-revision` makes the run fixed (`advance-after-reconcile=false`); without one, later receipts may
continue materializing desired state. A source revision superseded through `require-source-ref` returns
`active=false`.

Publish a full-tree or targeted forward rollback through the same change-gate behavior as the CLI:

```yaml
- id: rollback
  uses: NiklasRosenstein/gitopsctr@<commit-or-ref>
  with:
    operation: rollback
    package-source: action
    environment: prod
    rollback-revision: <historical-desired-sha>
    units: aws-application,frontend
    reason: Incident mitigation
```

An empty `units` input rolls back the full tree. The action exposes the standard `change-revision`,
`change-status`, `change-url`, `candidate-ref`, and `target-ref` outputs for direct publication or a gated pull
request.

Install the package bundled with the exact action revision while testing an unreleased change:

```yaml
- uses: NiklasRosenstein/gitopsctr@<commit-or-ref>
  with:
    operation: reconcile
    package-source: action
    environment: dev
    unit: application
```

Install the latest PyPI release (the default):

```yaml
- uses: NiklasRosenstein/gitopsctr@v1
  with:
    operation: advance
    environment: dev
    source-revision: ${{ github.sha }}
```

Install from a separate Git revision:

```yaml
- uses: NiklasRosenstein/gitopsctr@v1
  with:
    operation: promote
    package-source: git
    package-repository: NiklasRosenstein/gitopsctr
    package-revision: <commit-or-ref>
    from-environment: dev
    to-environment: staging
```

The caller must check out its deployment repository before invoking the action. For gated changes,
grant `contents: write` and `pull-requests: write`; for reconciliation receipts, grant
`contents: write`. Pass any cloud credentials and required external tools in the caller workflow.

## Releases

CI runs the mocked suite on Python 3.12, 3.13, and 3.14. Tags matching `v*` are accepted only when
the tag equals `v` plus the package version. After verification and an isolated package build, the
release workflow publishes through PyPI Trusted Publishing using the protected `pypi` environment.

## License

MIT
