1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141

infra / config / project.star [blame]

# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Project-wide settings and common structs (e.g. platform names)."""

platform = struct(
    ANDROID = "android",
    CROS = "cros",
    CROS_LTS = "cros-lts",
    FUCHSIA = "fuchsia",
    IOS = "ios",
    LINUX = "linux",
    MAC = "mac",
    WINDOWS = "windows",
)

PLATFORMS = tuple([getattr(platform, a) for a in dir(platform)])

def _platform_settings(
        *,
        description,  # buildifier: disable=unused-variable
        gardener_rotation = None):
    """Declare settings for a platform on the project.

    This provides the project-wide settings for a platform, which should be
    modified based on what channels the milestone is being shipped to for each
    platform.

    Args:
      * description - A string describing why the platform is enabled in the
        project. This is not used by the starlark, but enables providing some
        form of documentaion in the json file.
      * gardener_rotation - The name of a gardener rotation in which to include
        builders that are selected for the corresponding platform.
    """
    return struct(
        gardener_rotation = gardener_rotation,
    )

def _project_settings(
        *,
        project,
        project_title,
        ref,
        chrome_project,
        is_main,
        platforms = {}):
    """Declare settings for the project.

    This provides the central location for what must be modified when
    setting up the project for a new branch or when a branch changes category
    (e.g. moves from a standard release channel to the long-term support
    channel).

    Args:
      * project - The name of the LUCI project. No logic should depend on this
        value, it should only be used where the name of a project is required.
      * project_title - A string identifying the project in title contexts (e.g.
        titles of consoles). No conditional logic should depend on this value,
        it should only be used where the title of a project is required.
      * ref - The git ref containing the code for this branch.
      * chrome_project - The name of the corresponding chrome project. No logic
        should depend on this value, it should only be used where the name of a
        project is required.
      * ref - The git ref containing the code for this branch. No logic should
        depend on this value, it should only be used where a ref is required.
      * is_main - Whether or not this is the project for the main ref.
      * platforms - A mapping from a platform ID value to the settings for the
        platform. The valid platform ID values are the members of the platform
        struct. The settings for the platforms are dicts giving arguments for
        the _platform_settings function.

    Returns:
      A struct with attributes set to the input parameters. Additionally, the
      is_main attribute is set to True if branch_types is empty or False if
      branch_types is not empty.
    """
    if is_main:
        if platforms:
            fail("main project should not have any platforms set")
    else:
        if not platforms:
            fail("Non-main projects must have at least one platform set")
        invalid_platforms = [p for p in platforms if not p in PLATFORMS]
        if invalid_platforms:
            fail("The following platforms are invalid: {}".format(invalid_platforms))

    platforms = {k: _platform_settings(**v) for k, v in platforms.items()}

    return struct(
        project = project,
        project_title = project_title,
        ref = ref,
        chrome_project = chrome_project,
        is_main = is_main,
        platforms = platforms,
    )

settings = _project_settings(**json.decode(io.read_file("./settings.json")))

def _generate_project_pyl(ctx):
    ctx.output["project.pyl"] = "\n".join([
        "# This is a non-LUCI generated file",
        "# This is consumed by presubmit checks that need to validate the config",
        repr(dict(
            # On main, we want to ensure that we don't have source side specs
            # defined for non-existent builders
            # On branches, we don't want to re-generate the source side specs as
            # that would increase branch day toil and complicate cherry-picks
            validate_source_side_specs_have_builder = settings.is_main,
        )),
        "",
    ])

lucicfg.generator(_generate_project_pyl)

def _milestone_details(*, project, ref):
    """Define the details for an active milestone.

    Args:
      * project - The name of the LUCI project that is configured for the
        milestone.
      * ref - The ref in the git repository that contains the code for the
        milestone.
    """
    return struct(
        project = project,
        ref = ref,
    )

# The milestone names and branch numbers of branches that we have builders
# running for (including milestone-specific projects)
# Branch numbers and milestones can be viewed in the chromium column at
# https://chromiumdash.appspot.com/releases
# The 3rd portion of the version number is the branch number for the associated
# milestone
ACTIVE_MILESTONES = {
    m["name"]: _milestone_details(project = m["project"], ref = m["ref"])
    for m in json.decode(io.read_file("./milestones.json")).values()
} if settings.is_main else {}