Organization¶
The account above the repositories, declared as state and reviewed in the same plan. This is the shape the 0.5 line introduced.
# Governing the account itself, not only its repositories — the shape 0.5
# introduced.
#
# Everything under `organization` describes the account above the repositories:
# its public identity, what its members may do without asking, the custom
# properties it defines, and the rulesets it aims at repositories it selects.
#
# None of it has a command of its own. It appears in the same plan as the
# repository changes, grouped under a heading that names the account, and is
# confirmed the same way:
#
# export GITHUB_TOKEN=...
# octoform plan --config octoform.yml
# octoform apply --config octoform.yml
#
# The account is brought into agreement with this file before any repository is
# touched, so a lowered base permission is never briefly wider than it says.
#
# `example-org` is a placeholder. Replace it before running anything.
version: 1
owner: example-org
organization:
profile:
description: Platform engineering for the example estate
website: https://example.invalid
location: Remote
# Eight of these reach every repository the organisation owns, including
# ones this file never names, so the plan reports them as sensitive.
# `base_permission` is a floor: no repository policy can go below it.
members:
base_permission: read
create_public_repositories: false
create_private_repositories: true
fork_private_repositories: false
web_commit_signoff_required: true
# The organisation *defines* a property here. A repository *answers* it under
# its own `properties`, further down. The two are not interchangeable.
#
# The definition endpoint replaces rather than patches, so octoform reads the
# current definition and carries forward every field this file omits.
properties:
tier:
value_type: single_select
description: How closely this repository is watched
allowed_values: [bronze, silver, gold]
default_value: bronze
values_editable_by: org_actors
# Aimed at whatever the condition matches — which can include repositories
# this file never lists. Every organisation ruleset is reported as sensitive
# for that reason.
#
# Run it once with `enforcement: evaluate`. That reports what would have been
# blocked without blocking it, and it is the only honest way to find out what
# a property condition actually covers.
rulesets:
- name: watched-default-branches
enforcement: evaluate
target_branches: ['~DEFAULT_BRANCH']
block_force_push: true
block_deletion: true
require_pull_request: true
required_approvals: 1
repositories:
properties:
- name: tier
values: [gold, silver]
defaults:
merge:
delete_branch_on_merge: true
types:
service:
# The repository's half of the property defined above. Changing this can
# change which organisation rulesets reach the repository, which is why a
# property value is sensitive too.
properties:
tier: gold
repos:
example-service:
type: service
example-sandbox:
properties:
tier: bronze
What the plan looks like¶
Organization changes are grouped under a heading that cannot be mistaken for a repository name — a repository really can be called the same thing as the organization that owns it:
5 change(s) across 2 repositories:
(example-org: the organisation itself)
organization.profile.description: (unset) -> Platform engineering for the example estate
organization.members.base_permission: write -> read
organization.properties.tier: (unset) -> tier: single_select; bronze, silver, gold
organization.rulesets.watched-default-branches: (unset) -> evaluate on ~DEFAULT_BRANCH; ...
example-service
properties.tier: (unset) -> gold
The owner-level work is applied first, and the organization ruleset last within it, because it reaches furthest. See owner reconciliation.
The order to introduce this in¶
Do not apply all of it at once against an organization that has repositories in it. The three steps below each have a different failure mode, and separating them is what makes each one reviewable.
1. The profile alone¶
Comment out members, properties and rulesets for the first run. The
profile is normal risk and reaches nothing; it is the cheapest way to confirm
the token, the account and the file all work.
2. members, read carefully¶
base_permission is a floor under every repository the organization owns,
including repositories this file never names. Lowering it takes access away
from people who never appeared in any policy.
Before applying it, find out who that is:
3. The ruleset, in evaluate first¶
The example ships with enforcement: evaluate on purpose. A property condition
covers whatever currently answers tier: gold — including repositories added
tomorrow — and evaluate reports what would have been blocked without blocking
it.
Switch it to active once you have seen a week of that.
Definitions and values are different halves¶
organization.properties.tier defines the property. properties.tier under
types.service answers it. Neither can stand in for the other, and the same
word twice is GitHub's.
The definition endpoint replaces rather than patches, so octoform reads the current definition and carries forward every field this file does not mention. That is why correcting a description does not silently reset who may edit the values — which is exactly what earlier releases did.
What is not in this file¶
Membership of the organization itself. That is three commands, not a declaration, and this example deliberately leaves it out: a file that listed members authoritatively would remove somebody the first time a name was mistyped.
See the teams and access example for who is on which team and what each team may reach.