db9c8ad778
Change-Id: I01cbebd79e1d3470a4f00e55a228d57ac156b676
265 lines
11 KiB
Plaintext
265 lines
11 KiB
Plaintext
= Gerrit Code Review - Superproject subscription to submodules updates
|
|
|
|
[[automatic_update]]
|
|
== Description
|
|
Gerrit supports a custom git superproject feature for tracking submodules.
|
|
This feature is useful for automatic updates on superprojects whenever
|
|
a change is merged on tracked submodules.
|
|
|
|
When a superproject is subscribed to a submodule, it is not
|
|
required to push/merge commits to this superproject to update the
|
|
gitlink to the submodule. Whenever a commit is merged in a submodule,
|
|
its subscribed superproject is updated by Gerrit.
|
|
|
|
Imagine a superproject called 'super' having a branch called 'dev'
|
|
having subscribed to a submodule 'sub' on a branch 'dev-of-sub'. When a commit
|
|
is merged in branch 'dev-of-sub' of 'sub' project, Gerrit automatically
|
|
creates a new commit on branch 'dev' of 'super' updating the gitlink
|
|
to point to the just merged commit.
|
|
|
|
To take advantage of this feature, one should:
|
|
|
|
. ensure superproject subscriptions are enabled on the server via
|
|
link:config-gerrit.html#submodule.enableSuperProjectSubscriptions[submodule.enableSuperProjectSubscriptions]
|
|
. configure the submodule to allow having a superproject subscribed
|
|
. ensure the .gitmodules file of the superproject includes
|
|
.. a branch field
|
|
.. a url that starts with the link:config-gerrit.html#gerrit.canonicalWebUrl[`gerrit.canonicalWebUrl`]
|
|
|
|
When a commit in a project is merged, Gerrit checks for superprojects
|
|
that are subscribed to the project and automatically updates those
|
|
superprojects with a commit that updates the gitlink for the project.
|
|
|
|
This feature is enabled by default and can be disabled
|
|
via link:config-gerrit.html#submodule.enableSuperProjectSubscriptions[submodule.enableSuperProjectSubscriptions]
|
|
in the server configuration.
|
|
|
|
== Git submodules overview
|
|
|
|
Submodules are a Git feature that allows an external repository to be
|
|
attached inside a repository at a specific path. The objective here
|
|
is to provide a brief overview, further details can be found
|
|
in the official Git submodule documentation.
|
|
|
|
Imagine a repository called 'super' and another one called 'sub'.
|
|
Also consider 'sub' available in a running Gerrit instance on "server".
|
|
With this feature, one could attach 'sub' inside of 'super' repository
|
|
at path 'sub' by executing the following command when being inside
|
|
'super':
|
|
----
|
|
git submodule add ssh://server/sub sub
|
|
----
|
|
|
|
Still considering the above example, after its execution notice that
|
|
inside the local repository 'super' the 'sub' folder is considered a
|
|
gitlink to the external repository 'sub'. Also notice a file called
|
|
.gitmodules is created (it is a configuration file containing the
|
|
subscription of 'sub'). To provide the SHA-1 each gitlink points to in
|
|
the external repository, one should use the command:
|
|
----
|
|
git submodule status
|
|
----
|
|
|
|
In the example provided, if 'sub' is updated and 'super' is supposed
|
|
to see the latest SHA-1 (considering here 'sub' has only the master
|
|
branch), one should then commit the modified gitlink for 'sub' in
|
|
the 'super' project. Actually it would not even need to be an
|
|
external update, one could move to 'sub' folder (inside 'super'),
|
|
modify its content, commit, then move back to 'super' and
|
|
commit the modified gitlink for 'sub'.
|
|
|
|
== Creating a new subscription
|
|
|
|
=== Ensure the subscription is allowed
|
|
|
|
Gerrit has a complex access control system, where different repositories
|
|
can be accessed by different groups of people. To ensure that the submodule
|
|
related information is allowed to be exposed in the superproject,
|
|
the submodule needs to be configured to enable the superproject subscription.
|
|
In a submodule client, checkout the refs/meta/config branch and edit
|
|
the subscribe capabilities in the 'project.config' file:
|
|
----
|
|
git fetch <remote> refs/meta/config:refs/meta/config
|
|
git checkout refs/meta/config
|
|
$EDITOR project.config
|
|
----
|
|
and add the following lines:
|
|
----
|
|
[allowSuperproject "<superproject>"]
|
|
matching = <refspec>
|
|
----
|
|
where the 'superproject' should be the exact project name of the superproject.
|
|
The refspec defines which branches of the submodule are allowed to be
|
|
subscribed to which branches of the superproject. See below for
|
|
link:#acl_refspec[details]. Push the configuration for review and
|
|
submit the change:
|
|
----
|
|
git add project.config
|
|
git commit -m "Allow <superproject> to subscribe"
|
|
git push <remote> HEAD:refs/for/refs/meta/config
|
|
----
|
|
After the change is integrated a superproject subscription is possible.
|
|
|
|
The configuration is inherited from parent projects, such that you can have
|
|
a configuration in the "All-Projects" project like:
|
|
----
|
|
[allowSuperproject "my-only-superproject"]
|
|
matching = refs/heads/*:refs/heads/*
|
|
----
|
|
and then you don't have to worry about configuring the individual projects
|
|
any more. Child projects cannot negate the parent's configuration.
|
|
|
|
=== Defining the submodule branch
|
|
|
|
Since Gerrit manages subscriptions in the branch scope, we could have
|
|
a scenario having a project called 'super' having a branch 'integration'
|
|
subscribed to a project called 'sub' in branch 'integration', and also
|
|
having the same 'super' project but in branch 'dev' subscribed to the 'sub'
|
|
project in a branch called 'local-dev'.
|
|
|
|
After adding the git submodule to a super project, one should edit
|
|
the .gitmodules file to add a branch field to each submodule
|
|
section which is supposed to be subscribed.
|
|
|
|
As the branch field is a Gerrit-specific field it will not be filled
|
|
automatically by the git submodule command, so one needs to edit it
|
|
manually. Its value should indicate the branch of a submodule project
|
|
that when updated will trigger automatic update of its registered
|
|
gitlink.
|
|
|
|
The branch value could be "'.'" if the submodule project branch
|
|
has the same name as the destination branch of the commit having
|
|
gitlinks/.gitmodules file.
|
|
|
|
If the intention is to make use of the Gerrit feature described
|
|
here, one should always be sure to update the .gitmodules file after
|
|
adding submodules to a super project.
|
|
|
|
If a git submodule is added but the branch field is not added to the
|
|
.gitmodules file, Gerrit will not create a subscription for the
|
|
submodule and there will be no automatic updates to the superproject.
|
|
|
|
Whenever a commit is merged to a project, its project config is checked
|
|
to see if any potential superprojects are allowed to subscribe to it.
|
|
If so, the superproject is checked if a valid subscription exists
|
|
by checking the .gitmodules file for the a submodule which includes
|
|
a `branch` field and a url pointing to this server.
|
|
|
|
[[acl_refspec]]
|
|
=== The RefSpec in the allowSuperproject section
|
|
There are two options for specifying which branches can be subscribed
|
|
to. The most common is to set `allowSuperproject.<superproject>.matching`
|
|
to a Git-style refspec, which has the same syntax as the refspecs used
|
|
for pushing in Git. Regular expressions as found in the ACL configuration
|
|
are not supported.
|
|
|
|
The most restrictive refspec is allowing one specific branch of the
|
|
submodule to be subscribed to one specific branch of the superproject:
|
|
----
|
|
[allowSuperproject "<superproject>"]
|
|
matching = refs/heads/<submodule-branch>:refs/heads/<superproject-branch>
|
|
----
|
|
|
|
If you want to allow for a 1:1 mapping, i.e. 'master' maps to 'master',
|
|
'stable' maps to 'stable', but not allowing 'master' to be subscribed to
|
|
'stable':
|
|
----
|
|
[allowSuperproject "<superproject>"]
|
|
matching = refs/heads/*:refs/heads/*
|
|
----
|
|
|
|
To allow all refs matching one pattern to subscribe to all refs
|
|
matching another pattern, set `allowSuperproject.<superproject>.all`
|
|
to the patterns concatenated with a colon. For example, to make a
|
|
single branch available for subscription from all branches of the
|
|
superproject:
|
|
----
|
|
[allowSuperproject "<superproject>"]
|
|
all = refs/heads/<submodule-branch>:refs/heads/*
|
|
----
|
|
|
|
To make all branches available for subscription from all branches of
|
|
the superproject:
|
|
----
|
|
[allowSuperproject "<superproject>"]
|
|
all = refs/heads/*:refs/heads/*
|
|
----
|
|
|
|
=== Subscription Limitations
|
|
|
|
Gerrit will only automatically update superprojects where the
|
|
submodules are hosted on the same Gerrit instance as the
|
|
superproject. Gerrit determines this by checking that the URL of the
|
|
submodule specified in the .gitmodules file starts with
|
|
link:config-gerrit.html#gerrit.canonicalWebUrl[`gerrit.canonicalWebUrl`].
|
|
The protocol part is ignored in this check.
|
|
|
|
It is currently not possible to use the submodule subscription feature
|
|
with a canonical web URL that differs from the first part of
|
|
the submodule URL. Instead relative submodules should be used.
|
|
|
|
The Gerrit instance administrator should ensure that the canonical web
|
|
URL value is specified in its configuration file. Users should ensure
|
|
that they use the correct hostname of the running Gerrit instance when
|
|
adding submodule subscriptions.
|
|
|
|
When converting an existing submodule to use subscription by adding
|
|
a `branch` field into the .gitmodules file, Gerrit does not change
|
|
the revision of the submodule (i.e. update the superproject's gitlink)
|
|
until the next time the branch of the submodule advances. In other words,
|
|
if the currently used revision of the submodule is not the branch's head,
|
|
adding a subscription will not cause an immediate update to the head. In
|
|
this case the revision must be manually updated at the same time as adding
|
|
the subscription.
|
|
|
|
=== Relative submodules
|
|
|
|
To enable easier usage of Gerrit mirrors and/or distribution over
|
|
several protocols, such as plain git and HTTP(S) as well as SSH, one
|
|
can use relative submodules. This means that instead of providing the
|
|
entire URL to the submodule a relative path is stated in the
|
|
.gitmodules file.
|
|
|
|
Gerrit will try to match the entire project name of the submodule
|
|
including directories. Therefore it is important to supply the full
|
|
path name of the Gerrit project, not only relative to the super
|
|
repository. See the following example:
|
|
|
|
We have a super repository placed under a sub directory.
|
|
|
|
product/super_repository.git
|
|
|
|
To this repository we wish add a submodule "deeper" into the directory
|
|
structure.
|
|
|
|
product/framework/subcomponent.git
|
|
|
|
Now we need to edit the .gitmodules to include the complete path to
|
|
the Gerrit project. Observe that we need to use two "../" to include
|
|
the complete Gerrit project path.
|
|
|
|
path = subcomponent.git
|
|
url = ../../product/framework/subcomponent.git
|
|
branch = master
|
|
|
|
In contrast the following will not setup proper submodule
|
|
subscription, even if the submodule will be successfully cloned by git
|
|
from Gerrit.
|
|
|
|
path = subcomponent.git
|
|
url = ../framework/subcomponent.git
|
|
branch = master
|
|
|
|
== Removing Subscriptions
|
|
|
|
To remove a subscription, either disable the subscription from the
|
|
submodules configuration or remove the submodule or information thereof
|
|
(such as the branch field) in the superproject.
|
|
|
|
GERRIT
|
|
------
|
|
Part of link:index.html[Gerrit Code Review]
|
|
|
|
SEARCHBOX
|
|
---------
|