Some time ago, we updated Diffusion to import all refs in Git repositories (tags, branches, and refs like refs/pulls/1 [GitHub] and refs/changes/1 [Gerrit]).
There are some general inconsistencies with our handling of these refs, and with ref handling in general. The major problems are:
Forced Publishing of Non-Branch Refs: At time of writing, in master, commits reachable from non-branch refs are never "Autoclose" (that is, they do not apply Fixes T123 and do not close revisions), but they do always cause publishing effects (email, feed, audits, owners, Herald) unless publishing is completely disabled. This is often (probably "almost always") undesirable, see T11314 for an example. In effectively every case, no one wants refs/pulls/1 to publish, and there's currently no way to prevent this.
Autoclose vs Publish: I believe there is very little reason for the "Autoclose" and "Publish" behaviors to actually be separate. That is, there are very few use cases where users want a commit to trigger only Herald or only feed or only audits. These use cases do exist (see T9210 for an example of "Herald, No Feed") but they're overwhelmingly niche and off-label. In nearly every case, commits are either all-or-nothing and users either want full behavior or no behavior.
Tracked vs Permanent: Currently, installs often use "Track Only" to disable publish behaviors. This also disables importing the commits. This is an undesirable side effect: we generally want these commits to be imported and visible in the web UI (and we want to be able to reference them and do things like create revisions from them in the future), we just don't want to trigger a bunch of behavior after that.
To fix these issues, I'm making these changes:
Merging Autoclose and Publish: All "autoclose" and "publish" behaviors (email, notifications, feed, audits, herald, owners, tasks, revisions) are now under a single umbrella, not governed by separate "Autoclose" and "Publish" configuration. My expectation is that this simplifies configuration at effectively no cost, and that effectively all valid configurations set "Autoclose" and "Publish" to the same value, and that there is essentially no use case for triggering some of these behaviors but not all of them.
If or where use cases do exist (like T9210, or perhaps some stuff we'll discover like "run builds when I push to some weirdly named ref") I suspect we can find better ways to support the workflows.
This also fixes the inconsistent behavior of non-branch refs by disabling both "autoclose" and "publish" behaviors for them.
Renaming "Autoclose" to "Permanent Refs": The existing "Autoclose" setting is now "Permanent Refs". This generally aligns better with the most common use case, which is this:
I have a repository with some "permanent" branches like "master" and "stable", but I also push random branches like "tmp-epriestley-save-123-bugfix" to save my work, share code, etc.
In this case, users generally listed "Autoclose Only" as "master, stable" to disable autoclose on "tmp-epriestley", or "Track Only" as "master, stable" to disable autoclose and publishing.
Broadly, the new behavior is:
- By default, commits are considered non-permanent and don't trigger ANY autoclose/publishing behavior.
- Once a commit becomes an ancestor of a permanent ref, it becomes permanent and triggers ALL the behavior.
- By default, all branches are permanent refs and all other refs are not.
Fetch Only: A small set of cases are best handled by instructing Phabricator to fetch only certain refs from a remote.
Deprecating "Track Only": Now that "Permanent Refs" covers all triggered behavior (and "Fetch Only" exists), there is essentially no reason to use "Track Only", since "Track Only" was primarily (perhaps almost exclusively) used to stop publish behaviors, not to stop import into the web UI. "Track Only" rules can be moved to "Permanent Refs" and/or "Fetch Only" in effectively all cases.
Some time ago, we updated Diffusion to import all refs in Git repositories. This includes tags and arbitrary non-branch/tag refs, most commonly refs/pull/* created by GitHub pull requests and refs/changes/* created by Gerrit. When a repository is used as its own staging area, this also includes refs/tags/phabricator/diff/*.
The "Track Only" and "Autoclose Only" rule specifications were not been updated, and can only apply to branches: refs and tags are always tracked and always autoclose.
This primarily creates problems when these various "staging" refs trigger revision closure, and there's no real workaround for this because "Autoclose Only" can't exclude them.
A minimal approach might be this rule:
- Only branches can be "Autoclose". [Edit: This was already the behavior. There was confusion over "Autoclose" and "Publish" being separate behaviors.]
- [Edit: Actual approach is "Only branches can autoclose or publish."]
This probably fixes all the actual issues with no configuration changes. The only thing it might break is intentional use of release tags with no corresponding branches, but I believe this is rare or nonexistent.
A slightly less-minimal approach would be:
- Change the "Autoclose Only" rule list to allow specification of refs in the general case. The current ruleset master becomes branch(master) or similar, and so on.
This isn't terribly bad, but somewhat complex on our side and requires a somewhat-complex migration, and then installs with hundreds of repositories maybe need to go script an API call to update things or something, and we probably want to change the default behavior to "only branches can autoclose" anyway so this is just as breaking as the first change.
I'd generally like to move toward a world where "Track Only" is removed. The only "legitimate" use case I know of for "Track Only" (in a world where "Autoclose Only" works properly) is limiting what is fetched from an observed remote with tens of thousands of branches, primarily for performance reasons. This would be better implemented as "Fetch Only" with an explicit ref listing, versus "Track Only" with a complex pattern list. However, removing "Track Only" will require some configuration changes for most installs.
Entangled here to some degree are T8093 (virtualizing Git repository refs), arc save, and the many open requests to make Staging refs actually work properly (see T13278). Hypothetically, it would be nice to do most of these changes in a single release so we can say "a bunch of ref stuff has changed, here's the complete new behavior so you can update your stuff exactly once" rather than stringing it out over multiple releases.
Possibly see also T8936.