[cobalt_config] Moving cobalt config recipe here since cobalt-analytics
is going away and the config repo was moved to fuchsia.

Bug: 43843
Change-Id: Id8917626ada861b1967220cb857cb35edd705ae3
diff --git a/recipes/cobalt_config.expected/ci.json b/recipes/cobalt_config.expected/ci.json
new file mode 100644
index 0000000..01b85c7
--- /dev/null
+++ b/recipes/cobalt_config.expected/ci.json
@@ -0,0 +1,224 @@
+[
+  {
+    "cmd": [],
+    "name": "checkout"
+  },
+  {
+    "cmd": [],
+    "name": "checkout.ensure jiri",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[START_DIR]/cipd/jiri",
+      "-ensure-file",
+      "fuchsia/tools/jiri/${platform} git_revision:4bbab8725bd3c64b56e70af3d973d526cd894b49",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "name": "checkout.ensure jiri.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-git_revision:4bb\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"fuchsia/tools/jiri/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "init",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-analytics-opt=false",
+      "-rewrite-sso-to-https=true",
+      "-cache",
+      "[CACHE]/git",
+      "-shared",
+      "[START_DIR]"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri init",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "import",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-name",
+      "cobalt_config",
+      "-revision",
+      "2d72510e447ab60a9728aeea2362d8be2cbd7789",
+      "config.manifest",
+      "https://fuchsia.googlesource.com/manifest"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri import",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "update",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-autoupdate=false",
+      "-attempts=3",
+      "-run-hooks=false"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri update",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "run-hooks",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-attempts=3"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri run-hooks",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "source-manifest",
+      "-vv",
+      "-time",
+      "-j=50",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri source-manifest",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@{@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@  \"directories\": {@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@    \"manifest\": {@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@      \"git_checkout\": {@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@        \"repo_url\": \"https://fuchsia.googlesource.com/manifest\", @@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@        \"revision\": \"4c2b0da3c06341db5cebe4d02c78c93c3b2bd78b\"@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@      }@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@    }@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@  }@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@}@@@",
+      "@@@STEP_LOG_END@json.output[source manifest]@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "./cobaltb.py",
+      "setup"
+    ],
+    "cwd": "[START_DIR]/cobalt",
+    "name": "setup"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "./cobaltb.py",
+      "build",
+      "--out_dir",
+      "[START_DIR]/tools"
+    ],
+    "cwd": "[START_DIR]/cobalt",
+    "name": "build"
+  },
+  {
+    "cmd": [
+      "[START_DIR]/tools/config_parser",
+      "--output_file",
+      "[START_DIR]/new_config",
+      "--config_dir",
+      "[START_DIR]/config"
+    ],
+    "name": "check config"
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "HEAD^"
+    ],
+    "cwd": "[START_DIR]/config",
+    "name": "checkout parent"
+  },
+  {
+    "cmd": [
+      "[START_DIR]/tools/config_parser",
+      "--output_file",
+      "[START_DIR]/old_config",
+      "--config_dir",
+      "[START_DIR]/config"
+    ],
+    "name": "check parent config"
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "-"
+    ],
+    "cwd": "[START_DIR]/config",
+    "name": "checkout head"
+  },
+  {
+    "cmd": [
+      "git",
+      "show",
+      "-s",
+      "--format=%b"
+    ],
+    "cwd": "[START_DIR]/config",
+    "name": "read commit message"
+  },
+  {
+    "cmd": [
+      "[START_DIR]/tools/config_change_validator",
+      "--old_config",
+      "[START_DIR]/old_config",
+      "--new_config",
+      "[START_DIR]/new_config",
+      "--commit_msg",
+      ""
+    ],
+    "name": "validate change"
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipes/cobalt_config.expected/cq_try.json b/recipes/cobalt_config.expected/cq_try.json
new file mode 100644
index 0000000..4cc487a
--- /dev/null
+++ b/recipes/cobalt_config.expected/cq_try.json
@@ -0,0 +1,381 @@
+[
+  {
+    "cmd": [],
+    "name": "checkout"
+  },
+  {
+    "cmd": [],
+    "name": "checkout.ensure jiri",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[START_DIR]/cipd/jiri",
+      "-ensure-file",
+      "fuchsia/tools/jiri/${platform} git_revision:4bbab8725bd3c64b56e70af3d973d526cd894b49",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "name": "checkout.ensure jiri.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-git_revision:4bb\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"fuchsia/tools/jiri/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "init",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-analytics-opt=false",
+      "-rewrite-sso-to-https=true",
+      "-cache",
+      "[CACHE]/git",
+      "-shared",
+      "[START_DIR]"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri init",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "checkout.ensure gerrit",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "cipd",
+      "ensure",
+      "-root",
+      "[START_DIR]/cipd/gerrit",
+      "-ensure-file",
+      "infra/tools/luci/gerrit/${platform} latest",
+      "-json-output",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "name": "checkout.ensure gerrit.ensure_installed",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@2@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"result\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"instance_id\": \"resolved-instance_id-of-latest----------\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"package\": \"infra/tools/luci/gerrit/resolved-platform\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }@@@",
+      "@@@STEP_LOG_LINE@json.output@    ]@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/gerrit/gerrit",
+      "change-detail",
+      "-host",
+      "https://fuchsia-review.googlesource.com",
+      "-input",
+      "{\"change_id\": \"cobalt_config~123456\", \"params\": {\"o\": [\"ALL_REVISIONS\"]}}",
+      "-output",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "name": "checkout.get change details",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"branch\": \"master\", @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"revisions\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"a1b2c3\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"_number\": 7, @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"ref\": \"refs/changes/00/100/7\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    }, @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"d4e5f6\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"_number\": 3, @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"ref\": \"refs/changes/00/100/3\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    }, @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"g7h8i9\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"_number\": 9, @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"ref\": \"refs/changes/00/100/9\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    }@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "import",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-name",
+      "cobalt_config",
+      "-remote-branch",
+      "master",
+      "config.manifest",
+      "https://fuchsia.googlesource.com/manifest"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri import",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "update",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-autoupdate=false",
+      "-attempts=3",
+      "-run-hooks=false",
+      "-fetch-packages=false"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri update",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "patch",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-host",
+      "https://fuchsia-review.googlesource.com",
+      "-project",
+      "cobalt_config",
+      "-rebase=true",
+      "refs/changes/00/100/7"
+    ],
+    "name": "checkout.jiri patch",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "update",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-autoupdate=false",
+      "-attempts=3",
+      "-gc=true",
+      "-rebase-tracked",
+      "-local-manifest=true",
+      "-run-hooks=false",
+      "-fetch-packages=false"
+    ],
+    "name": "checkout.jiri update (2)",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "run-hooks",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-attempts=3",
+      "-local-manifest=true"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri run-hooks",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "fetch-packages",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-attempts=3",
+      "-local-manifest=true"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri fetch-packages",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "source-manifest",
+      "-vv",
+      "-time",
+      "-j=50",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "name": "checkout.jiri source-manifest",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@{@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@  \"directories\": {@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@    \"manifest\": {@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@      \"git_checkout\": {@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@        \"repo_url\": \"https://fuchsia.googlesource.com/manifest\", @@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@        \"revision\": \"4c2b0da3c06341db5cebe4d02c78c93c3b2bd78b\"@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@      }@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@    }@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@  }@@@",
+      "@@@STEP_LOG_LINE@json.output[source manifest]@}@@@",
+      "@@@STEP_LOG_END@json.output[source manifest]@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "[START_DIR]/cipd/jiri/jiri",
+      "project",
+      "-vv",
+      "-time",
+      "-j=50",
+      "-json-output",
+      "/path/to/tmp/json",
+      "cobalt_config"
+    ],
+    "infra_step": true,
+    "name": "jiri project",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@json.output@[@@@",
+      "@@@STEP_LOG_LINE@json.output@  {@@@",
+      "@@@STEP_LOG_LINE@json.output@    \"branches\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"(HEAD detached at c22471f)\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    ], @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"current_branch\": \"\", @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"name\": \"cobalt_config\", @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"path\": \"path/to/cobalt_config\", @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"remote\": \"https://fuchsia.googlesource.com/cobalt_config\", @@@",
+      "@@@STEP_LOG_LINE@json.output@    \"revision\": \"c22471f4e3f842ae18dd9adec82ed9eb78ed1127\"@@@",
+      "@@@STEP_LOG_LINE@json.output@  }@@@",
+      "@@@STEP_LOG_LINE@json.output@]@@@",
+      "@@@STEP_LOG_END@json.output@@@",
+      "@@@SET_BUILD_PROPERTY@got_revision@\"c22471f4e3f842ae18dd9adec82ed9eb78ed1127\"@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "./cobaltb.py",
+      "setup"
+    ],
+    "cwd": "[START_DIR]/cobalt",
+    "name": "setup"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "./cobaltb.py",
+      "build",
+      "--out_dir",
+      "[START_DIR]/tools"
+    ],
+    "cwd": "[START_DIR]/cobalt",
+    "name": "build"
+  },
+  {
+    "cmd": [
+      "[START_DIR]/tools/config_parser",
+      "--output_file",
+      "[START_DIR]/new_config",
+      "--config_dir",
+      "[START_DIR]/config"
+    ],
+    "name": "check config"
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "HEAD^"
+    ],
+    "cwd": "[START_DIR]/config",
+    "name": "checkout parent"
+  },
+  {
+    "cmd": [
+      "[START_DIR]/tools/config_parser",
+      "--output_file",
+      "[START_DIR]/old_config",
+      "--config_dir",
+      "[START_DIR]/config"
+    ],
+    "name": "check parent config"
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "-"
+    ],
+    "cwd": "[START_DIR]/config",
+    "name": "checkout head"
+  },
+  {
+    "cmd": [
+      "git",
+      "show",
+      "-s",
+      "--format=%b"
+    ],
+    "cwd": "[START_DIR]/config",
+    "name": "read commit message"
+  },
+  {
+    "cmd": [
+      "[START_DIR]/tools/config_change_validator",
+      "--old_config",
+      "[START_DIR]/old_config",
+      "--new_config",
+      "[START_DIR]/new_config",
+      "--commit_msg",
+      ""
+    ],
+    "name": "validate change"
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipes/cobalt_config.py b/recipes/cobalt_config.py
new file mode 100644
index 0000000..6b478dc
--- /dev/null
+++ b/recipes/cobalt_config.py
@@ -0,0 +1,120 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Recipe for building and testing cobalt-registry.
+
+Uses Cobalt's cobaltb.py script to build the config_parser tool,
+then runs it on Cobalt's `config` repo.
+"""
+
+from recipe_engine.recipe_api import Property
+
+DEPS = [
+    'fuchsia/checkout',
+    'fuchsia/jiri',
+    'recipe_engine/buildbucket',
+    'recipe_engine/context',
+    'recipe_engine/path',
+    'recipe_engine/properties',
+    'recipe_engine/python',
+    'recipe_engine/raw_io',
+    'recipe_engine/step',
+]
+
+PROPERTIES = {
+    'remote':
+        Property(kind=str, help='URL to remote repo containing Jira manifest'),
+    'manifest':
+        Property(
+            kind=str, help='Jiri manifest file to use, relative to `remote`'),
+}
+
+# The name of the gerrit project tested by this recipe.
+MANIFEST_PROJECT_NAME = 'cobalt_config'
+
+
+def RunSteps(api, remote, manifest):
+  # Check out the project from the specified manifest.
+  with api.context(infra_steps=True):
+    build_input = api.buildbucket.build.input
+    api.checkout.with_options(
+        path=api.path['start_dir'],
+        manifest=manifest,
+        remote=remote,
+        project=MANIFEST_PROJECT_NAME,
+        build_input=build_input)
+
+    revision = build_input.gitiles_commit.id
+    if not revision:
+      revision = api.jiri.project([MANIFEST_PROJECT_NAME
+                                  ]).json.output[0]['revision']
+      api.step.active_result.presentation.properties['got_revision'] = revision
+
+  # Root of the cobalt repo as checked out by the manifest.
+  cobalt_src_dir = api.path['start_dir'].join('cobalt')
+  tools_dir = api.path['start_dir'].join('tools')
+
+  # Build config_parser.
+  with api.context(cwd=cobalt_src_dir):
+    api.python('setup', './cobaltb.py', args=['setup'])
+    api.python('build', './cobaltb.py', args=['build', '--out_dir', tools_dir])
+
+  config_parser_bin = tools_dir.join('config_parser')
+  config_validator_bin = tools_dir.join('config_change_validator')
+
+  # Root of the config repo as checked out by the manifest.
+  config_src_dir = api.path['start_dir'].join('config')
+
+  # Run config_parser on the config repo checkout.
+  api.step('check config', [
+      config_parser_bin,
+      '--output_file',
+      api.path['start_dir'].join('new_config'),
+      '--config_dir',
+      config_src_dir,
+  ])
+
+  with api.context(cwd=config_src_dir):
+    api.step('checkout parent', ['git', 'checkout', 'HEAD^'])
+
+  api.step('check parent config', [
+      config_parser_bin,
+      '--output_file',
+      api.path['start_dir'].join('old_config'),
+      '--config_dir',
+      config_src_dir,
+  ])
+
+  commit_msg = ""
+  with api.context(cwd=config_src_dir):
+    api.step('checkout head', ['git', 'checkout', '-'])
+    commit_msg = api.step(
+        'read commit message', ['git', 'show', '-s', '--format=%b'],
+        stdout=api.raw_io.output()).stdout
+
+  api.step('validate change', [
+      config_validator_bin,
+      '--old_config',
+      api.path['start_dir'].join('old_config'),
+      '--new_config',
+      api.path['start_dir'].join('new_config'),
+      '--commit_msg',
+      commit_msg,
+  ])
+
+
+def GenTests(api):
+  yield (api.test('ci') + api.buildbucket.ci_build(
+      git_repo='https://fuchsia.googlesource.com/cobalt_config',) +
+         api.properties(
+             remote='https://fuchsia.googlesource.com/manifest',
+             manifest='config.manifest',
+             project='cobalt_config',
+         ))
+  yield (api.test('cq_try') + api.buildbucket.try_build(
+      git_repo='https://fuchsia.googlesource.com/cobalt_config',) +
+         api.properties.tryserver(
+             remote='https://fuchsia.googlesource.com/manifest',
+             manifest='config.manifest',
+             project='cobalt_config',
+         ))