nosync-quiet option added courtesy Robin Johnson (Gentoo project)
[gitolite-doc.git] / docs / templates.mkd
blobcfb996fc7d365faaf463fce58d8466ff521f2bf2
1 # setting up and using templates
3 ----
5 This feature was added late September 2017, after 3.6.7.  In terms of
6 versioning, it will be part of 3.6.8, or you could just grab the latest from
7 github.
9 # overview
11 This feature describes a new method of specifying gitolite rules.
13 A "template" is a set of gitolite access rules with a name.  A gitolite
14 "expert" can setup a suitable set of templates, and then actual repos can use
15 one or more of these templates, according to their need.
17 A simple example will illustrate.  It's split into two parts.
19 First, the **template definitions**, where the rules comprising each template
20 are defined:
22 ```gitolite
23 # (obligatory warning: the order of the following lines matters!)
25 repo @is_public
26     R                           =   @all
28 repo @is_suspended
29     -                           =   @all
31 repo @has_personal_refs
32     RW+     dev/USER/           =   teamleads team
33     -       dev/                =   @all
34     RW+     refs/tags/dev/USER/ =   teamleads team
35     -       refs/tags/dev/      =   @all
37 repo @has_releases
38     RW      refs/tags/v[0-9]    =   release_managers
39     -       refs/tags/v[0-9]    =   @all
41 repo @base
42     RW+                         =   teamleads
43     RW                          =   team
44     R                           =   READERS
45 ```
47 Next, you have the **template data** section (i.e., the lines between the
48 `begin` and `end` lines you see in the example below).  This is where you
49 declare actual repos (`foo` and `bar` below), giving each a set of one or more
50 templates it will **use**, and map users to any roles that the template may
51 require.
53 ```gitolite
54 =begin template-data
56 repo foo = base is_public has_releases
57     teamleads           =   sitaram
58     team                =   dilbert wally
59     READERS             =   ashok
60     release_managers    =   alice
62 repo bar = base has_personal_refs
63     teamleads           =   han
64     team                =   luke chewie
66 =end
67 ```
69 Notice that `foo` and `bar` use different sets of templates: `foo` is a
70 public-readable repo that controls who can push versioned tags (releases),
71 while `bar` is a basic repo which supports [personal branches][perbr].
73 # advantages
75 There are a few advantages with this approach:
77 1.  Maintaining access rules is much simpler.  Just choose an appropriate set
78     of "template names", assign people to roles, and you're done.
80     There's no need to understand the intricacies of gitolite's ruleset.  (The
81     person who *wrote* the templates needs to, but not the person who is
82     maintaining dozens of repos by merely *using* those templates).
84     *Heck you can probably roll a nice GUI around this.  Finally!*
86 2.  Reduces boilerplate.  A good example is the "personal branches" one above
87     -- why have each of those 4 lines in every repo if you can instead refer
88     to the feature by name somehow
90     A conf using this is often smaller, and definitely cleaner.
92 2.  Reduces possible errors.  This should follow from the previous point.  It
93     is easy to make mistakes when changing something due to some new
94     requirement.  Did you remember to put in the two "deny" rules in the
95     personal branches example above?
97     What if management decides to suspend pushes to one particular repo, and
98     you best choice was to add a catch-all "deny everyone" rule.  Did you
99     remember to put it at the top?  (If the templates are written as above
100     (including the *order in which you see them*), all you have to do is add
101     the word `is_suspended` somewhere in the list of templates that apply to
102     repo `bar`.)
104 3.  Makes gitolite compile much faster, especially if you have thousands (or
105     tens of thousands) of repos.
107 # how does it work?
109 ## a repo and its users
111 The [wildcard](wild) repos feature already has a way to dissociate the actual
112 user names from the rule set in gitolite.conf.  For example, you can say
114 ```gitolite
115 repo foo/..*
116     C       =   @managers
117     RW+     =   WRITERS
118     R       =   READERS
119     ...(etc.)...
122 This lets any "manager" create a repo whose name matches the pattern, then
123 assign arbitrary users to WRITERS and other roles using the [`perms`
124 command][perms].  These role assignments are stored in a simple text file
125 within the repository's bare directory (i.e., `~/repositories/$REPO.git`), so
126 they are specific to that repo, **not** common to all the repos matching that
127 pattern (as they would be if you listed the users in gitolite.conf directly).
129 In other words, we've taken the actual users (say alice, bob, etc) out of the
130 gitolite.conf file, and thus any changes to the users/roles no longer need to
131 involve gitolite.conf.
133 ## a repo and its *rules*
135 In a "duh! Why didn't I think of this till now" moment, I realised I can do
136 the same for the *rules* that apply to a repo -- take that association out of
137 gitolite.conf.  That is what the `repo foo = [...list of templates...]` lines
138 are doing.
140 This list of templates is also stored in a plain text file just like the one
141 that contains the user/role mappings, and in the same directory.
143 # usage and syntax
145 First, you have to add all the new "roles" to the `ROLES` hash in
146 `~/.gitolite.rc`.  If you edit that file, you'll see two pre-created roles
147 `READERS` and `WRITERS`.  Using the same syntax (including the trailing
148 comma), add any other roles you would like to use.  In our example up at the
149 top, the role names are `team`, `teamleads`, and `release_managers`.
151 !!! danger ""
152     Rolenames must start with a letter, and be made up of only alphanumeric
153     characters and the underscore -- basically the same rules as a shell
154     variable.
156 Next, you define the templates, in the right order.  This is the only order
157 that matters (not the order in which the templates are *used* in any
158 particular repo in the template-data section).
160 Thus, this is also the part that requires gitolite rules expertise, but it's
161 hopefully a one-time or once-in-a-while thing.  (Or you can ask on the mailing
162 list!)
164 Finally, you define actual repos in gitolite.conf as shown in the example
165 above (including the `=begin template-data` and `=end` lines).  For each repo,
166 you specify what templates it will use, and then you map actual users to the
167 role names from those templates.
169 A few additional points:
171 1.  Not all role names need to be mapped to users (for example, we did not
172     assign any `READERS` to repo `bar`, even though the `base` template
173     specifies that role).
175 2.  Within the gitolite.conf file, the placement of the template-data section
176     does not matter.  (It's not even parsed by the conf compiler, which
177     completely skips it.  It's processed by a new program that is run
178     internally, and directly manipulates the gl-repo-groups and gl-perms
179     files).
181 3.  You can even have multiple template-data sections, with normal
182     gitolite.conf rules, group definitions, `config` and `option` lines, etc.,
183     in between.  (That's why there's a begin *and* an end!)
185     If you use `include` files, I strongly suggest -- in the interest of
186     sanity -- that you do not let a template-data section cross over a file
187     boundary (i.e., define the `begin` in one file, and the `end` in another).
188     It will work, if you understand what order the files are picked up, but
189     I'd still avoid such tricks if I were you!
191 4.  If you want to insert some rules for a repo that is defined in a
192     template-data section, you need to be careful where you place it.
194     Rules defined by templates are deemed to occur exactly where the template
195     **definition** is.  So, speaking of repo foo, pretend that the line `repo @is_public`
196     was replaced by `repo foo`, and similarly for `repo @has_releases` and
197     `repo @base`.
199     !!! note ""
200         While we're on the subject, you can also pretend the role names on the
201         right hand side of the rules are replaced by the actual user names you
202         supplied in the template-data section.
204     In the example above, say you wanted to insert a new rule for repo foo,
205     which says that no one can rewind `master`, not even `teamleads`.
207     Clearly, the rules you need are:
209     ```gitolite
210     repo foo
211         RW  master      =   sitaram
212         # notice we had to expand 'teamleads' from foo's definition in the
213         # template-data section
214         -   master      =   @all
215     ```
217     But where do you place them?  The answer is, *at least before the `base`
218     template is defined*.  Otherwise, the `RW+` in the base template will kick
219     in, and this restriction will fail to take effect.
221     Having said that, I would rather add a new template to deal with this,
222     placing it just before `repo @base`):
224     ```gitolite
225     repo @limits_master
226         RW  master      =   teamleads
227         -   master      =   @all
228     ```
230     and then add `limits_master` to the list of templates that `foo` uses.
232     This has the advantages of being able to reuse that logic for other repos,
233     but even more important, you're avoiding repeating the actual teamleads
234     name(s) in more than one place!  (Potentially a huge future inconsistency
235     if someone forgot to update both places when the teamleads change!)
237 5.  You can also do multiple repos in one shot, as well as repo groups:
239     ```gitolite
240     # before the '=begin' line
241     @repogroup1 = r1 r2 r3
242     ...
243     ...
244     ...
246     =begin template-data
247     repo foo bar @repogroup1 = base is_public has_releases
248         ...
249         ...
250         ...
251     =end
252     ```
254 # bypassing gitolite.conf for *huge* sites
256 Some sites have all their access control information in a web-based system,
257 and generate gitolite.conf as needed.  If they have tens of thousands of
258 repos, this "generated" gitolite.conf becomes humongous, and slows down
259 compiles.  Worse, the more repos you have, the more churn you have in terms of
260 changes to users accesses, so you do more compiles per hour than a smaller
261 site, which only makes things worse!
263 With this feature, you can bypass gitolite.conf and directly create/update
264 those text files to change the users and rule-sets for a given repo.  It
265 doesn't even have to touch gitolite or gitolite.conf (assuming the templates
266 and roles are already defined in gitolite.conf and `~/.gitolite.rc` of
267 course!)
269 ## generating the text files externally
271 The actual text files involved are very simple.  Remember these files go into
272 `~/repositories/$REPO.git` (or more accurately, `$(gitolite query-rc GL_REPO_BASE)/$REPO.git`).
274 For the example above, here's the file `gl-repo-groups` in repo foo:
276     $ cat ~/repositories/foo.git/gl-repo-groups
277     base is_public has_releases
279 As you can see, this text is just what is after the `=` sign in the `repo`
280 line in the template data section of gitolite.conf.
282 and the file `gl-perms` is:
284     $ cat ~/repositories/foo.git/gl-perms
285     teamleads           =   sitaram
286     team                =   dilbert wally
287     READERS             =   ashok
288     release_managers    =   alice
290 Again, this text is exactly the same as in the gitolite.conf!
292 ## creating new repos
294 Gitolite has no mechanism to create repos out of thin air, so if you don't
295 want to go via gitolite.conf, one way to do this is to add the following lines
296 to the conf file (one-time):
298 ```gitolite
299 repo [a-zA-Z0-9].*
300     C   =   gitolite-admin
303 and then, at the server, run this:
305     GL_USER=gitolite-admin gitolite create foo/bar
307 That creates the repo, and you can now populate its `gl-perms` and
308 `gl-repo-groups` files.
310 # thanks to...
312 ...pingou on irc, and the Fedora project, for having 42,000 repos in a conf
313 file over 560,000 lines long.  Which made me think about this real hard for
314 days, including two false starts (one of which I published and have just now
315 reverted, and one which was so kludgey I refuse to acknowledge it exists --
316 thank God I did not publish that!)
318 # miscellanea
320 This feature is not the same as [wild]() repos; repos here are created by the
321 gitolite admin or a server-side backend, *not* by a gitolite user.  (However,
322 this feature piggy-backs on a lot of the code for wild repos, adding just a
323 wee bit -- the "duh" comment earlier in this document -- to complete it).
325 [perms]: user#setget-additional-permissions-for-repos-you-created
326 [perbr]: user#personal-branches
327 [group]: conf#group-definitions
328 [accum]: conf#rule-accumulation