Re: [OpenStack-Infra] Some branch issues with Zuul

2017-10-27 Thread James E. Blair
cor...@inaugust.com (James E. Blair) writes:

 ...
> The Changes
> ===
>
> I believe the following changes will address all five problems and
> achieve both design goals:
>
> a) Apply inheritance at the same time as variance
>
> Rather than applying inheritance at configuration time, apply it at the
> time the job is frozen before being run.  We can perform a depth-first
> traversal up the hierarchy of parents, applying all of the matching
> variants at each level as we return down.  With the following graph
> (where lines indicate parent relationships):
>
> 0 base
>  /\
> 1 devstack  2 devstack  4 altbase
>  \/ |
>3 tempest5 tempest
>   /  \
>  6 foo  7 foo
>
> Would have the following jobs applied in order:
>
> 0 base, 1 devstack, 2 devstack, 3 tempest, 4 altbase,
> 5 tempest, 6 foo, 7 foo
>
> b) Add an implicit branch matcher to the master branch
>
> Generally this will add clarity to projects with multiple branches,
> however, if we always add the an implicit branch matcher, then it makes
> it difficult to use repos like zuul-jobs to define jobs that run
> everywhere.  So do this only if the project has multiple branches.  If
> the project only has a single branch, omit the implicit branch matcher.
>
> c) Add a config option to disable the implicit branch matcher
>
> There are some times when an implicit branch matcher on master may be
> undesirable.  For example when tempest was becoming branchless, it had
> multiple branches, but we would have wanted the jobs defined on master
> to be applicable everywhere.  Or if, for some reason, we wanted to
> create a feature branch on zuul-jobs.  For these cases, it's necessary
> to have an option to disable the implicit branch matcher.  We can add a
> new kind of configuration object to zuul.yaml, for example:
>
>   - meta:
>   implicit-branch-matcher: False
>
> Which would be intended only to apply to the current branch.  Or we
> could add an option to the tenant config file, so the admin can indicate
> that a certain project should not have an implicit branch matcher
> applied to certain branches.
>
...
>
> (d) Remove the implicit run playbook
>
> This is not required to solve any of the problems stated, however, it
> does make the solution to problem (4) even more explicit.
>
> Moreover, despite being an initial proponent of the implicit playbook, I
> have found that in practice, we have so many jobs that do not have
> playbooks at all (i.e., we're making heavy use of inheritance and
> variance) that it is becoming difficult to determine where to look for a
> job's run playbook.  Declaring the run playbook explicitly will help
> with discoverability.

These changes have been implemented and merged into the feature/zuulv3
branch.

I also included a change to accept file extensions on playbook paths,
with the intention that we will deprecate the option to omit extensions.

-Jim

___
OpenStack-Infra mailing list
OpenStack-Infra@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra

Re: [OpenStack-Infra] Some branch issues with Zuul

2017-10-25 Thread James E. Blair
Doug Hellmann  writes:

> In the discussion yesterday, and in the emails today, you've implied
> that there is an ordering to job definitions beyond inheritance. Is that
> discovery order documented somewhere? If not, is it simple enough to
> describe in a few sentences here? Are repositories scanned in a
> particular order, for example? Or is it based on something else?

There's some discussion of it here:

https://docs.openstack.org/infra/zuul/feature/zuulv3/user/config.html#job

  When Zuul decides to run a job, it performs a process known as
  freezing the job. Because any number of job variants may be
  applicable, Zuul collects all of the matching variants and applies
  them in the order they appeared in the configuration. The resulting
  frozen job is built from attributes gathered from all of the matching
  variants. In this way, exactly what is run is dependent on the
  pipeline, project, branch, and content of the item.

Because top-level job variants may only be defined in the same project
(so that one project may not alter the jobs defined by another project),
the order that the repos are loaded doesn't matter for this; only the
order that branches are loaded within a repo.  That's not specified by
the documentation, though it is currently 'master' followed by others in
alphabetical order.

The proposed changes would reduce the importance of that, since master
will have an implied branch matcher, meaning that by default, jobs in
master won't have an effect on other branches.  I'd probably still leave
the order the same though, in case someone wanted to override that
behavior.

In practice, and especially with the proposed change to have an implied
branch matcher on master, the ordering aspect is most likely to be
visible when a user adds several variants of a job in the same file.

The order that the repos themselves are loaded is important, however, in
inheritance.  They are loaded in a defined order (the order they appear
in the main.yaml tenant configuration file), and currently, a job may
only inherit from another job which has already been defined.  So we
manually put more "general-use" projects (e.g., devstack, tempest)
earlier in the config.  I would characterize this as an oversight, and
was planning on fixing it soon regardless, however, the proposal to
perform late-binding inheritance will solve it as well (since the
inheritance path would be determined when the job is run, well after all
the configuration is loaded).

There's some more discussion of the repo loading order here:

  
https://docs.openstack.org/infra/zuul/feature/zuulv3/admin/tenants.html#attr-tenant

-Jim

___
OpenStack-Infra mailing list
OpenStack-Infra@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra

Re: [OpenStack-Infra] Some branch issues with Zuul

2017-10-25 Thread James E. Blair
Andrea Frittoli  writes:

> We will need somewhere in the logs a description of the traversal that was
> done to build the final job. I believe that would help debugging issues that
> may arise from unexpected inheritance behaviour.
>
> Andrea Frittoli (andreaf)

Yes!  We have that to some degree today, and it's been very helpful
lately. :)

Example:

  
http://logs.openstack.org/33/509233/7/check/tox-linters/23b39f2/zuul-info/inventory.yaml

  _inheritance_path:
  - 'inherit from '
  - 'inherit from '
  - 'inherit from '
  - 'self '
  - 'apply variant '

The var name has an underscore because it's undocumented and (very!)
likely to change.  It's basically just a some debug lines rendered as a
list at the moment.  Once it settles down, I plan on turning it into a
proper data structure and documenting it.  Then it may be appropriate to
output it in the console log.

In the late-binding proposal, the distinction between inheritance and
variance is largely lost, and it essentially just turns into a list of
'apply variant' lines.  I think even that would still be enough,
However, I may be able to improve the output slightly and get a bit more
context back.  I'll look at that when I make the final version of the
patch.

-Jim

___
OpenStack-Infra mailing list
OpenStack-Infra@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra

Re: [OpenStack-Infra] Some branch issues with Zuul

2017-10-25 Thread Doug Hellmann
Excerpts from corvus's message of 2017-10-24 15:22:51 -0700:
> Hi,
> 
> A number of issues related to how jobs are defined and run on projects
> with stable branches have come up recently.  I believe they are all
> related, and they, as well as the solutions to them, must be considered
> together.
> 
> 
> The Problems
> 
> 
> I've identified the following five problems:
> 
> 1) Parents should have variants applied
> 
> Currently inheritance and variance are distinct.  Inheritance modifies a
> job's configuration statically at the time the configuration is loaded.
> Variants are applied dynamically right before the job runs.
> 
> That means that when a job starts, we pick a single job to start with,
> then apply variants of that particular job.  But since the inheritance
> has already been applied, any variants which a user may expect to apply
> to a parent job will not be applied.  When the inheritance chain is
> created at configuration time, only the "reference" definition of the
> job is used -- that is, the first appearance of the job.
> 
> In other words, more than likely, most jobs defined in a stable branch
> are going to inherit from a parent job defined on the master branch --
> even if that parent job has a stable branch variant.
> 
> 2) Variants may cause parents to be ignored
> 
> We currently ignore the parent attribute on a job variant.  If we did
> not, then when the variant is applied, it would pull in all of the
> attributes of its parent, which is likely to be on the master branch
> (since its parent will, as in #1, be the reference definition).
> 
> This ignoring of the parent attribute happens at configuration time
> (naturally, since that is when inheritance is applied).
> 
> This means that if the first job that matches a change is a variant
> (i.e., the reference definition of a job has a non-matching branch
> matcher), this top-level variant job will not actually have a parent.

In the discussion yesterday, and in the emails today, you've implied
that there is an ordering to job definitions beyond inheritance. Is that
discovery order documented somewhere? If not, is it simple enough to
describe in a few sentences here? Are repositories scanned in a
particular order, for example? Or is it based on something else?

Doug

> 
> 3) Variants may add duplicate pre/post playbooks
> 
> Currently, the master branch does not have an implied branch matcher, so
> jobs that exist on master and stable branches will generally be derived
> from both.
> 
> If such a job adds a pre or post playbook, the job that is ultimately
> created and run for a change on the stable branch may have those added
> by both the variant defined on the master branch as well as that defined
> on the stable branch (since pre and post playbooks are cumulative).
> 
> 4) Variants on branches without explicit playbooks should use branch
>playbooks
> 
> Whenever a job includes a pre-run, run (including the implicit run), or
> post-run playbook, Zuul remembers where and uses that branch of that
> repo to run that playbook.  If a job were constructed from the master
> branch, and then had a stable branch variant applied but did not repeat
> the pre-run, run, or post-run attributes from the master, then Zuul
> would end up attempting to run the playbook from the master branch
> rather than the stable.
> 
> 5) The master branch should have implied branch matchers
> 
> Currently jobs defined in an untrusted project on any branch other than
> 'master' have an implicit branch matcher applied to them.  This is what
> allows the version of a job in a stable branch to only affect the stable
> branch.  The fact that there is no implicit branch matcher applied to
> the master branch is what allows jobs defined in zuul-jobs to run on
> changes to any branch.
> 
> However, this also means that jobs on stable branches are frequently
> built from variants on both the master and stable branch.  This may work
> for a short while, but will fail as soon as someone wants to add
> something to the master branch which should not exist on the stable
> branch (e.g., enabling a new service by default).
> 
> 
> The Design Considerations
> =
> 
> In looking at these, I believe they have come about because of two
> design goals which we did not appreciate were in moderate tension with
> each other:
> 
> A) In-repo configuration for a project should apply to that branch.
> Changing the behavior of a job on a stable branch should merely involve
> changing the configuration or playbook in that stable branch.  When a
> project branches master to create a new stable branch, both branches
> should initially have the same content and behavior, but then evolve
> independently.
> 
> B) We should be able to define jobs not only in a central repository
> such as project-config, but a central *untrusted* repository such as
> zuul-jobs or openstack-zuul-jobs.
> 
> I think these are valid and important to keep in mind as we 

Re: [OpenStack-Infra] Some branch issues with Zuul

2017-10-25 Thread Andrea Frittoli
On Wed, Oct 25, 2017 at 12:23 AM James E. Blair  wrote:

> Hi,
>
> A number of issues related to how jobs are defined and run on projects
> with stable branches have come up recently.  I believe they are all
> related, and they, as well as the solutions to them, must be considered
> together.
>
>
> The Problems
> 
>
> I've identified the following five problems:
>
> 1) Parents should have variants applied
>
> Currently inheritance and variance are distinct.  Inheritance modifies a
> job's configuration statically at the time the configuration is loaded.
> Variants are applied dynamically right before the job runs.
>
> That means that when a job starts, we pick a single job to start with,
> then apply variants of that particular job.  But since the inheritance
> has already been applied, any variants which a user may expect to apply
> to a parent job will not be applied.  When the inheritance chain is
> created at configuration time, only the "reference" definition of the
> job is used -- that is, the first appearance of the job.
>
> In other words, more than likely, most jobs defined in a stable branch
> are going to inherit from a parent job defined on the master branch --
> even if that parent job has a stable branch variant.
>
> 2) Variants may cause parents to be ignored
>
> We currently ignore the parent attribute on a job variant.  If we did
> not, then when the variant is applied, it would pull in all of the
> attributes of its parent, which is likely to be on the master branch
> (since its parent will, as in #1, be the reference definition).
>
> This ignoring of the parent attribute happens at configuration time
> (naturally, since that is when inheritance is applied).
>
> This means that if the first job that matches a change is a variant
> (i.e., the reference definition of a job has a non-matching branch
> matcher), this top-level variant job will not actually have a parent.
>
> 3) Variants may add duplicate pre/post playbooks
>
> Currently, the master branch does not have an implied branch matcher, so
> jobs that exist on master and stable branches will generally be derived
> from both.
>
> If such a job adds a pre or post playbook, the job that is ultimately
> created and run for a change on the stable branch may have those added
> by both the variant defined on the master branch as well as that defined
> on the stable branch (since pre and post playbooks are cumulative).
>
> 4) Variants on branches without explicit playbooks should use branch
>playbooks
>
> Whenever a job includes a pre-run, run (including the implicit run), or
> post-run playbook, Zuul remembers where and uses that branch of that
> repo to run that playbook.  If a job were constructed from the master
> branch, and then had a stable branch variant applied but did not repeat
> the pre-run, run, or post-run attributes from the master, then Zuul
> would end up attempting to run the playbook from the master branch
> rather than the stable.
>
> 5) The master branch should have implied branch matchers
>
> Currently jobs defined in an untrusted project on any branch other than
> 'master' have an implicit branch matcher applied to them.  This is what
> allows the version of a job in a stable branch to only affect the stable
> branch.  The fact that there is no implicit branch matcher applied to
> the master branch is what allows jobs defined in zuul-jobs to run on
> changes to any branch.
>
> However, this also means that jobs on stable branches are frequently
> built from variants on both the master and stable branch.  This may work
> for a short while, but will fail as soon as someone wants to add
> something to the master branch which should not exist on the stable
> branch (e.g., enabling a new service by default).
>
>
> The Design Considerations
> =
>
> In looking at these, I believe they have come about because of two
> design goals which we did not appreciate were in moderate tension with
> each other:
>
> A) In-repo configuration for a project should apply to that branch.
> Changing the behavior of a job on a stable branch should merely involve
> changing the configuration or playbook in that stable branch.  When a
> project branches master to create a new stable branch, both branches
> should initially have the same content and behavior, but then evolve
> independently.
>
> B) We should be able to define jobs not only in a central repository
> such as project-config, but a central *untrusted* repository such as
> zuul-jobs or openstack-zuul-jobs.
>
> I think these are valid and important to keep in mind as we consider
> solutions.
>
>
> The Changes
> ===
>
> I believe the following changes will address all five problems and
> achieve both design goals:
>
> a) Apply inheritance at the same time as variance
>
> Rather than applying inheritance at configuration time, apply it at the
> time the job is frozen before being run.  We can perform a depth-first
> 

Re: [OpenStack-Infra] Some branch issues with Zuul

2017-10-24 Thread Tobias Henkel

Wow, I have (almost) nothing to add.


On 10/25/2017 12:22 AM, James E. Blair wrote:

[...]

c) Add a config option to disable the implicit branch matcher

There are some times when an implicit branch matcher on master may be
undesirable.  For example when tempest was becoming branchless, it had
multiple branches, but we would have wanted the jobs defined on master
to be applicable everywhere.  Or if, for some reason, we wanted to
create a feature branch on zuul-jobs.  For these cases, it's necessary
to have an option to disable the implicit branch matcher.  We can add a
new kind of configuration object to zuul.yaml, for example:

   - meta:
   implicit-branch-matcher: False

Which would be intended only to apply to the current branch.  Or we
could add an option to the tenant config file, so the admin can indicate
that a certain project should not have an implicit branch matcher
applied to certain branches.
I vote for adding this to the zuul.yaml as I think this should belong to 
the

project and not to the admin. Further this is more flexible as changes to
the tenant config requires some deployment and full zuul reload which
I think creates a potentially high process and runtime cost for changing 
this.


All of these changes sound logical to me.

Thanks for this well written excerpt :)

Tobias

___
OpenStack-Infra mailing list
OpenStack-Infra@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra

[OpenStack-Infra] Some branch issues with Zuul

2017-10-24 Thread James E. Blair
Hi,

A number of issues related to how jobs are defined and run on projects
with stable branches have come up recently.  I believe they are all
related, and they, as well as the solutions to them, must be considered
together.


The Problems


I've identified the following five problems:

1) Parents should have variants applied

Currently inheritance and variance are distinct.  Inheritance modifies a
job's configuration statically at the time the configuration is loaded.
Variants are applied dynamically right before the job runs.

That means that when a job starts, we pick a single job to start with,
then apply variants of that particular job.  But since the inheritance
has already been applied, any variants which a user may expect to apply
to a parent job will not be applied.  When the inheritance chain is
created at configuration time, only the "reference" definition of the
job is used -- that is, the first appearance of the job.

In other words, more than likely, most jobs defined in a stable branch
are going to inherit from a parent job defined on the master branch --
even if that parent job has a stable branch variant.

2) Variants may cause parents to be ignored

We currently ignore the parent attribute on a job variant.  If we did
not, then when the variant is applied, it would pull in all of the
attributes of its parent, which is likely to be on the master branch
(since its parent will, as in #1, be the reference definition).

This ignoring of the parent attribute happens at configuration time
(naturally, since that is when inheritance is applied).

This means that if the first job that matches a change is a variant
(i.e., the reference definition of a job has a non-matching branch
matcher), this top-level variant job will not actually have a parent.

3) Variants may add duplicate pre/post playbooks

Currently, the master branch does not have an implied branch matcher, so
jobs that exist on master and stable branches will generally be derived
from both.

If such a job adds a pre or post playbook, the job that is ultimately
created and run for a change on the stable branch may have those added
by both the variant defined on the master branch as well as that defined
on the stable branch (since pre and post playbooks are cumulative).

4) Variants on branches without explicit playbooks should use branch
   playbooks

Whenever a job includes a pre-run, run (including the implicit run), or
post-run playbook, Zuul remembers where and uses that branch of that
repo to run that playbook.  If a job were constructed from the master
branch, and then had a stable branch variant applied but did not repeat
the pre-run, run, or post-run attributes from the master, then Zuul
would end up attempting to run the playbook from the master branch
rather than the stable.

5) The master branch should have implied branch matchers

Currently jobs defined in an untrusted project on any branch other than
'master' have an implicit branch matcher applied to them.  This is what
allows the version of a job in a stable branch to only affect the stable
branch.  The fact that there is no implicit branch matcher applied to
the master branch is what allows jobs defined in zuul-jobs to run on
changes to any branch.

However, this also means that jobs on stable branches are frequently
built from variants on both the master and stable branch.  This may work
for a short while, but will fail as soon as someone wants to add
something to the master branch which should not exist on the stable
branch (e.g., enabling a new service by default).


The Design Considerations
=

In looking at these, I believe they have come about because of two
design goals which we did not appreciate were in moderate tension with
each other:

A) In-repo configuration for a project should apply to that branch.
Changing the behavior of a job on a stable branch should merely involve
changing the configuration or playbook in that stable branch.  When a
project branches master to create a new stable branch, both branches
should initially have the same content and behavior, but then evolve
independently.

B) We should be able to define jobs not only in a central repository
such as project-config, but a central *untrusted* repository such as
zuul-jobs or openstack-zuul-jobs.

I think these are valid and important to keep in mind as we consider
solutions.


The Changes
===

I believe the following changes will address all five problems and
achieve both design goals:

a) Apply inheritance at the same time as variance

Rather than applying inheritance at configuration time, apply it at the
time the job is frozen before being run.  We can perform a depth-first
traversal up the hierarchy of parents, applying all of the matching
variants at each level as we return down.  With the following graph
(where lines indicate parent relationships):

0 base
 /\
1 devstack  2 devstack  4 altbase
 \/ |