| = 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 |
| --------- |