Multi-owner¶
One document, two accounts, and the shared policy written once. This is the shape the 0.4 line introduced, and the reason the rest of the release exists.
# Two accounts governed by one reviewed document — the shape 0.4 introduced.
#
# What is worth noticing here is what is *not* repeated. The root `defaults`
# and the named policy under `policies` are written once, and each account
# takes what applies to it. An account is not a copy of the document; it is a
# selection within it.
#
# `example-org` and `example-personal` are placeholders — replace them, then:
# export GITHUB_TOKEN=...
# octoform plan --config octoform.yml --owner example-org
# octoform plan --config octoform.yml # both, one at a time
#
# Accounts run in declaration order and their reports never interleave. By
# default a failure in one does not stop the other; add --fail-fast to stop at
# the first.
version: 1
defaults:
merge:
delete_branch_on_merge: true
allow_merge_commit: true
allow_rebase: false
policies:
published-library:
features:
issues: true
security:
secret_scanning: true
secret_scanning_push_protection: true
owners:
# An organisation: rulesets are available at owner level, and custom
# properties exist, so classification can be persisted.
example-org:
classify:
rules:
- when: { file_exists: package.json }
type: npm-package
types:
npm-package:
policies: [published-library]
default_branch:
name: main
# A personal account: the same named policy applies, but nothing here
# depends on an organisation-only feature. `octoform inspect capabilities`
# reports any declaration that would not apply, with the reason.
example-personal:
repos:
example-tool:
policies: [published-library]
What is shared and what is not¶
defaults and policies sit at the root, so both accounts see them. Each
account's own block states only what is true of that account: the organization
classifies repositories and applies the named policy to a type, the personal
account applies the same named policy to one repository by name.
An account block is not a copy of the document. It is a selection within it, and reading one top to bottom still tells the whole story for that account — a referenced policy never overrides a key the referencing layer states itself.
Running it¶
Without --owner, both accounts run, one at a time, in declaration order.
Their reports never interleave. A failure in one does not stop the other
unless you pass --fail-fast, and the run's exit class is the most severe any
account produced.
A --repo name that exists under both accounts is rejected rather than
guessed at, and the error lists the qualified forms that would resolve it:
Before the first run against a new account¶
This reports each account's kind, its numeric identity, whether organization-wide rulesets are available, and any declaration that does not apply to that kind of account. The personal account here declares nothing organization-only, but the check is what proves it rather than assumes it.
Migrating an existing single-owner file¶
A file that names its account in a root owner field keeps its exact meaning
and produces the same plans. Nothing has to change. When you want this shape:
It previews by default, preserves comments and ordering, and refuses --write
when the file has uncommitted changes, so the conversion is always reviewable
as a diff. See octoform config.