# `ownership` When matching a file to scopes, the default behavior is to only apply the last matching scope (remember, scopes are defined in order). This is most similar to how CODEOWNERS typically work. The default value for `ownership` is an empty string (`""`), which means the last matched scope is the owner. PullApprove has two other modes of file ownership: - `append` - Establish joint-ownership of a file by appending this scope to any future matching scopes. - `global` - Allow this scope to approve on behalf of any future matching scopes. Wherever a scope name is printed — the CLI, the pull request page, and the review workspace — a non-default ownership shows up as a marker on the name: `+scope` for `append` and `*scope` for `global`. ## `append` With appended ownership, **each matching scope is required to approve the PR**. ```toml [[scopes]] name = "dependencies" ownership = "append" paths = ["**/*/package.json"] [[scopes]] name = "app" paths = ["app/**/*"] ``` ```console $ git diff --name-only app/package.json $ pullapprove match --diff app/package.json -> app dependencies ``` ## `global` With global ownership, **the global scope can approve the PR which overrides the status of the primary matched scope**. If a global scope uses `request`, its reviewers are requested on every PR it matches, like any other scope. A global scope needs `require` of at least 1. Once a global scope is satisfied, every file it matches passes, so with `require = 0` (the default) every PR would pass before anyone looked at it. PullApprove reports that as a config error instead. The usual shape is "these people can approve anything, but don't bug them on every PR": set `require = 1` and leave `request` at its default of `0`. ```toml [[scopes]] name = "global" ownership = "global" paths = ["**/*"] reviewers = ["@org/leads"] require = 1 [[scopes]] name = "app" paths = ["app/**/*"] ``` ```console $ git diff --name-only app/package.json $ pullapprove match --diff app/package.json -> app *global ``` A few things to keep in mind: - A file that no other scope matches (anything outside `app/` in the example above) needs an approval from the global scope itself. With `request = 0` nobody gets asked for it, so you probably want a catch-all scope listed first. - A "changes requested" review still blocks the PR, even after a global scope has approved it. - [`author_value`](author-value.md) and [`unless`](unless.md) satisfy a global scope the same way they satisfy any other scope. A satisfied global scope passes every file it matches, so a global scope that counts its authors can pass their PRs with no review at all.