Skip to content

Instantly share code, notes, and snippets.

@gmr
Last active February 8, 2018 22:45
Show Gist options
  • Select an option

  • Save gmr/6107050 to your computer and use it in GitHub Desktop.

Select an option

Save gmr/6107050 to your computer and use it in GitHub Desktop.

Revisions

  1. Gavin M. Roy revised this gist Aug 6, 2013. 1 changed file with 8 additions and 11 deletions.
    19 changes: 8 additions & 11 deletions 5-knife_production_upload.sh
    Original file line number Diff line number Diff line change
    @@ -34,31 +34,28 @@ set -f; IFS=$'\n'; for LINE in $GITLOG; do
    COOKBOOK=`echo $LINE | perl -n -e '/^\w{40}\s+(Adding|Updating)\sdependency\scookbook\s([\w-]+)\s(to.|)*$/m && {print "$2\n"}'`
    DEPENDENCY_COOKBOOKS+=("$COOKBOOK")

    elif [ "$OBJECT" == "data_bags" ]; then
    elif [ "$OBJECT" == "data_bags" ]; then
    cd $WORKSPACE/data_bags
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-\_]+\/[\w\-\_]+\.json)$/m && {print "$1\n"}'`
    FILES=`git diff-tree --no-commit-id --name-only -r $(git log --oneline -n 1 | awk '{print $1}')`
    cd $WORKSPACE
    for data_bag in $FILES
    do
    for data_bag in ${FILES[@]}; do
    knife data bag from file ${data_bag/\// }
    done

    elif [ "$OBJECT" == "environments" ]; then
    cd $WORKSPACE/environments
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    FILES=`git diff-tree --no-commit-id --name-only -r $(git log --oneline -n 1 | awk '{print $1}')`
    cd $WORKSPACE
    for environment in $FILES
    do
    for environment in ${FILES[@]}; do
    knife environment from file $environment
    done

    elif [ "$OBJECT" == "roles" ]; then
    cd $WORKSPACE/roles
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    FILES=`git diff-tree --no-commit-id --name-only -r $(git log --oneline -n 1 | awk '{print $1}')`
    cd $WORKSPACE
    for role in FILES
    do
    knife role from file $f
    for role in ${FILES[@]}; do
    knife role from file $role
    done
    fi

  2. Gavin M. Roy revised this gist Aug 6, 2013. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions 5-knife_production_upload.sh
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,7 @@ set -f; IFS=$'\n'; for LINE in $GITLOG; do

    elif [ "$OBJECT" == "data_bags" ]; then
    cd $WORKSPACE/data_bags
    FILES=`git diff-tree --no-commit-id --name-only -r ${LINE:0:40}`
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-\_]+\/[\w\-\_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for data_bag in $FILES
    do
    @@ -45,7 +45,7 @@ set -f; IFS=$'\n'; for LINE in $GITLOG; do

    elif [ "$OBJECT" == "environments" ]; then
    cd $WORKSPACE/environments
    FILES=`git diff-tree --no-commit-id --name-only -r ${LINE:0:40}`
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for environment in $FILES
    do
    @@ -54,7 +54,7 @@ set -f; IFS=$'\n'; for LINE in $GITLOG; do

    elif [ "$OBJECT" == "roles" ]; then
    cd $WORKSPACE/roles
    FILES=`git diff-tree --no-commit-id --name-only -r ${LINE:0:40}`
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for role in FILES
    do
  3. Gavin M. Roy revised this gist Aug 6, 2013. 1 changed file with 53 additions and 33 deletions.
    86 changes: 53 additions & 33 deletions 5-knife_production_upload.sh
    Original file line number Diff line number Diff line change
    @@ -15,40 +15,60 @@ export KNIFE_VALIDATION_CLIENT_NAME="chef-validator"
    export KNIFE_VALIDATION_CLIENT_KEY="$HOME/.chef/validation.pem"
    export KNIFE_COOKBOOK_PATH=$WORKSPACE/cookbooks

    OBJECT=`git log --pretty=oneline -n 1 | perl -n -e '/^(\w{40})\s+(Adding|Updating)\s(cookbook|dependency\scookbook|environments|data_bags|roles)/ && {print "$3"}'`
    COOKBOOKS=()
    DEPENDENCY_COOKBOOKS=()
    GITLOG=`git log -n 100 --pretty=oneline`
    set -f; IFS=$'\n'; for LINE in $GITLOG; do
    if [ "${LINE:0:40}" == "$GIT_PREVIOUS_COMMIT" ]; then
    echo "Exiting on changeset ${LINE:0:40}";
    break
    fi

    if [ "$OBJECT" == "cookbook" ] || [ "$OBJECT" == "dependency cookbook" ]; then
    OBJECT=`echo $LINE | perl -n -e '/^(\w{40})\s+(Adding|Updating)\s(cookbook|dependency\scookbook|environments|data_bags|roles)/ && {print "$3"}'`

    # Extract the cookbook to upload
    COOKBOOK=`git log --pretty=oneline -n 1 | perl -n -e '/^\w{40}\s+((Adding|Updating)\sdependency\scookbook\s([\w-]+)\sto.*$|(Adding|Updating)\scookbook\s([\w-_]+)\sto.*$)/m && {print "$3$5\n"}'`
    if [ "$OBJECT" == "cookbook" ]; then
    COOKBOOK=`echo $LINE | perl -n -e '/^\w{40}\s+(Adding|Updating)\scookbook\s([\w-_]+)(\sto|).*$/m && {print "$2\n"}'`
    COOKBOOKS+=("$COOKBOOK")

    elif [ "$OBJECT" == "dependency cookbook" ]; then
    COOKBOOK=`echo $LINE | perl -n -e '/^\w{40}\s+(Adding|Updating)\sdependency\scookbook\s([\w-]+)\s(to.|)*$/m && {print "$2\n"}'`
    DEPENDENCY_COOKBOOKS+=("$COOKBOOK")

    # Upload the cookbook
    knife cookbook upload $COOKBOOK
    elif [ "$OBJECT" == "data_bags" ]; then
    cd $WORKSPACE/data_bags
    FILES=`git diff-tree --no-commit-id --name-only -r ${LINE:0:40}`
    cd $WORKSPACE
    for data_bag in $FILES
    do
    knife data bag from file ${data_bag/\// }
    done

    elif [ "$OBJECT" == "environments" ]; then
    cd $WORKSPACE/environments
    FILES=`git diff-tree --no-commit-id --name-only -r ${LINE:0:40}`
    cd $WORKSPACE
    for environment in $FILES
    do
    knife environment from file $environment
    done

    elif [ "$OBJECT" == "roles" ]; then
    cd $WORKSPACE/roles
    FILES=`git diff-tree --no-commit-id --name-only -r ${LINE:0:40}`
    cd $WORKSPACE
    for role in FILES
    do
    knife role from file $f
    done
    fi

    elif [ "$OBJECT" == "data_bags" ]; then
    cd $WORKSPACE/data_bags
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-\_]+\/[\w\-\_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for data_bag in $FILES
    do
    knife data bag from file ${data_bag/\// }
    done

    elif [ "$OBJECT" == "environments" ]; then
    cd $WORKSPACE/environments
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for environment in $FILES
    do
    knife environment from file $environment
    done

    elif [ "$OBJECT" == "roles" ]; then
    cd $WORKSPACE/roles
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for role in FILES
    do
    knife role from file $role
    done
    fi
    done

    UPLOAD=($(printf "%s\n" "${DEPENDENCY_COOKBOOKS[@]}" | sort -u ))
    for COOKBOOK in ${UPLOAD[@]}; do
    knife cookbook upload $COOKBOOK
    done
    UPLOAD=($(printf "%s\n" "${COOKBOOKS[@]}" | sort -u ))
    for COOKBOOK in ${UPLOAD[@]}; do
    knife cookbook upload $COOKBOOK
    done
  4. Gavin M. Roy revised this gist Jul 30, 2013. 1 changed file with 7 additions and 8 deletions.
    15 changes: 7 additions & 8 deletions 2-cookbook-dependency.py
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,3 @@
    # This script processes the dependencies.json file in a cookbook and either adds
    # or updates the submodule information in the master repo, this is run in a job
    # per cookbook "Execute Python" build step *after* the cookbook-update.sh build
    # step

    import json
    import os
    import subprocess
    @@ -15,12 +10,14 @@
    dependencies = '%s/dependencies.json' % cookbook_path


    def execute(command):
    def execute(command, ignorable=False):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    if p.returncode:
    print 'Command failure [%s] returned %s' % (' '.join(command),
    p.returncode)
    if ignorable:
    return False
    print
    print stderr
    print
    @@ -48,14 +45,16 @@ def execute(command):

    os.chdir(dependency_path)
    if cookbooks[name].get('branch'):
    execute(['git', 'checkout', '-b', cookbooks[name].get('branch', 'master')])
    if not execute(['git', 'checkout', '-b', cookbooks[name].get('branch', 'master')], True):
    execute(['git', 'checkout', cookbooks[name].get('branch', 'master')])

    execute(['git', 'pull', '-f', '-u', 'origin', cookbooks[name].get('branch', 'master')])
    os.chdir(base_path)

    if 'revision' in cookbooks[name]:
    # Change to that revision
    os.chdir(dependency_path)
    execute(['git', 'reset', '--hard', cookbooks[name]['revision']])
    execute(['git', 'reset', '--hard', str(cookbooks[name]['revision'])])

    # Commit the specific revision for that cookbook
    os.chdir(base_path)
  5. Gavin M. Roy revised this gist Jul 29, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 5-knife_production_upload.sh
    Original file line number Diff line number Diff line change
    @@ -49,6 +49,6 @@ elif [ "$OBJECT" == "roles" ]; then
    cd $WORKSPACE
    for role in FILES
    do
    knife role from file $f
    knife role from file $role
    done
    fi
  6. Gavin M. Roy revised this gist Jul 29, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 0-dependencies.json
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    {
    "cookbooks": {
    "build-essential": {
    "url": "git://github.com/opscode-cookbooks/build-essential.git"
    "url": "git://github.com/opscode-cookbooks/build-essential.git",
    "branch": "master",
    "revision": "2991fc6e5448e5b2378eb6882e9c1ce557d828f0"
    },
  7. Gavin M. Roy revised this gist Jul 29, 2013. 3 changed files with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions 0-auto-manged-chef-repo.md
    Original file line number Diff line number Diff line change
    @@ -22,8 +22,8 @@ Each cookbook has a Jenkins job that recives a Github callback when changes are

    `1-cookbook-update.sh` updates the chef repo for the updated cookbook, while `2-cookbook-dependency.py` adds or updates cookbook dependencies. Note that at this time these scripts do not do conflict resolution for different versions or repositories of the same dependency across cookbooks. `3-chef-repo-push.sh` pushes the submodule updates back to Github.

    `1-other-build.sh` is used for each respository that contains the roles, environments, and data bags. Roles, environments and data bags each have a Jenkins job which like the cookbooks will update the submodule reference in the `chef-repo` repository.
    `4-other-build.sh` is used for each respository that contains the roles, environments, and data bags. Roles, environments and data bags each have a Jenkins job which like the cookbooks will update the submodule reference in the `chef-repo` repository.

    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `4-knife_production_upload.sh` script can extract the proper type of update to run and what cookbook(s) to update.
    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `5-knife_production_upload.sh` script can extract the proper type of update to run and what cookbook(s) to update.

    If you want to make sure that cookbooks pass tests prior to inclusion, tt should be trivial to add build-steps in Jenkins that execute unit tests or other acceptance testing prior to making the commits to chef-repo.
    File renamed without changes.
  8. Gavin M. Roy revised this gist Jul 29, 2013. 3 changed files with 6 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions 0-auto-manged-chef-repo.md
    Original file line number Diff line number Diff line change
    @@ -18,11 +18,12 @@ Each cookbook has a Jenkins job that recives a Github callback when changes are

    - 1-cookbook-update.sh
    - 2-cookbook-dependency.py
    - 3-chef-repo-push.sh

    `1-cookbook-update.sh` updates the chef repo for the updated cookbook, while `2-cookbook-dependency.py` adds or updates cookbook dependencies. Note that at this time these scripts do not do conflict resolution for different versions or repositories of the same dependency across cookbooks.
    `1-cookbook-update.sh` updates the chef repo for the updated cookbook, while `2-cookbook-dependency.py` adds or updates cookbook dependencies. Note that at this time these scripts do not do conflict resolution for different versions or repositories of the same dependency across cookbooks. `3-chef-repo-push.sh` pushes the submodule updates back to Github.

    `1-other-build.sh` is used for each respository that contains the roles, environments, and data bags. Roles, environments and data bags each have a Jenkins job which like the cookbooks will update the submodule reference in the `chef-repo` repository.

    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `2-knife_production_upload.sh` script can extract the proper type of update to run and what cookbook(s) to update.
    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `4-knife_production_upload.sh` script can extract the proper type of update to run and what cookbook(s) to update.

    If you want to make sure that cookbooks pass tests prior to inclusion, tt should be trivial to add build-steps in Jenkins that execute unit tests or other acceptance testing prior to making the commits to chef-repo.
    3 changes: 3 additions & 0 deletions 3-chef-repo-push.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    # This is the third buildstep for a cookbook
    cd $WORKSPACE/repo
    git push origin master
  9. Gavin M. Roy revised this gist Jul 29, 2013. 2 changed files with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions 0-auto-manged-chef-repo.md
    Original file line number Diff line number Diff line change
    @@ -14,15 +14,15 @@ Our `chef-repo` directory looks something like:
    So that we can use git submodules for dependency cookbooks that are maintained by a third parties, there is a `dependencies.json` file placed in the root of each cookbook. See `0-dependencies.json` and `0-dependencies-json-notes.md`.

    Each cookbook has a Jenkins job that recives a github callback when changes are pushed into it. These jobs all have two build steps:
    Each cookbook has a Jenkins job that recives a Github callback when changes are pushed into it. These jobs all have two build steps:

    - 1-cookbook-update.sh
    - 2-cookbook-dependency.py

    `1-cookbook-update.sh` updates the chef repo for the updated cookbook, while `2-cookbook-dependency.py` adds or updates cookbook dependencies. At this time these scripts do not do conflict resolution for different versions of the same dependency.
    `1-cookbook-update.sh` updates the chef repo for the updated cookbook, while `2-cookbook-dependency.py` adds or updates cookbook dependencies. Note that at this time these scripts do not do conflict resolution for different versions or repositories of the same dependency across cookbooks.

    `1-other-build.sh` is used for each respository that contains the roles, environments, and data bags. Roles, environments and data bags each have a Jenkins job which like the cookbooks will update the submodule reference in the `chef-repo` repository.

    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `2-knife_production_upload.sh` can extract the proper type of update to run and what cookbook(s) to update.
    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `2-knife_production_upload.sh` script can extract the proper type of update to run and what cookbook(s) to update.

    If you want to make sure that cookbooks pass tests prior to inclusion, tt should be trivial to add build-steps in Jenkins that execute unit tests or other acceptance testing prior to making the commits to chef-repo.
    File renamed without changes.
  10. Gavin M. Roy revised this gist Jul 29, 2013. 2 changed files with 17 additions and 4 deletions.
    21 changes: 17 additions & 4 deletions 0-auto-manged-chef-repo.md
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    The files in this gist are for having Jenkins automatically manage a chef repository using git submodules. This allows for clean, clutter free management of individual cookbooks, and individual respositories for roles, environments and data bags.
    The files in this gist are for having Jenkins automatically manage a chef repository using git submodules. This allows for clean, clutter free management of individual cookbooks, and individual respositories for roles, environments and data bags in our `chef-repo`.

    It relies on using Github (we use Github Enterprise) and Jenkins in combination with the Jenkins Github plugin to notify Jenkins when a repository has changed.
    The process relies on using Github (we use Github Enterprise) and Jenkins in combination with the Jenkins Github plugin to notify Jenkins when a repository has changed.

    Our chef-repo directory looks something like:
    Our `chef-repo` directory looks something like:

    chef-repo
    - cookbooks
    @@ -12,4 +12,17 @@ Our chef-repo directory looks something like:
    - roles (git submodule managed by Jenkins)
    - All other normal files and directories
    Each cookbook has a Jenkins job that recives a github callback when changes are pushed into it. These jobs all ove two build steps:
    So that we can use git submodules for dependency cookbooks that are maintained by a third parties, there is a `dependencies.json` file placed in the root of each cookbook. See `0-dependencies.json` and `0-dependencies-json-notes.md`.

    Each cookbook has a Jenkins job that recives a github callback when changes are pushed into it. These jobs all have two build steps:

    - 1-cookbook-update.sh
    - 2-cookbook-dependency.py

    `1-cookbook-update.sh` updates the chef repo for the updated cookbook, while `2-cookbook-dependency.py` adds or updates cookbook dependencies. At this time these scripts do not do conflict resolution for different versions of the same dependency.

    `1-other-build.sh` is used for each respository that contains the roles, environments, and data bags. Roles, environments and data bags each have a Jenkins job which like the cookbooks will update the submodule reference in the `chef-repo` repository.

    When `chef-repo` is updated, Github makes a callback to Jenkins which triggers a job to upload changes to the Chef server. All of the scripts use a uniform commit message style to chef-repo so that the `2-knife_production_upload.sh` can extract the proper type of update to run and what cookbook(s) to update.

    If you want to make sure that cookbooks pass tests prior to inclusion, tt should be trivial to add build-steps in Jenkins that execute unit tests or other acceptance testing prior to making the commits to chef-repo.
    File renamed without changes.
  11. Gavin M. Roy revised this gist Jul 29, 2013. 2 changed files with 16 additions and 2 deletions.
    16 changes: 15 additions & 1 deletion 0-auto-manged-chef-repo.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,15 @@
    The files in this gist are for having Jenkins automatically manage a chef repository using git submodules. This allows for clean, clutter free management of individual cookbooks, and individual respositories for roles, environments and data bags.
    The files in this gist are for having Jenkins automatically manage a chef repository using git submodules. This allows for clean, clutter free management of individual cookbooks, and individual respositories for roles, environments and data bags.

    It relies on using Github (we use Github Enterprise) and Jenkins in combination with the Jenkins Github plugin to notify Jenkins when a repository has changed.

    Our chef-repo directory looks something like:

    chef-repo
    - cookbooks
    - Each cookbook is a git submodule managed by Jenkins
    - data_bags (git submodule managed by Jenkins)
    - environments (git submodule managed by Jenkins)
    - roles (git submodule managed by Jenkins)
    - All other normal files and directories
    Each cookbook has a Jenkins job that recives a github callback when changes are pushed into it. These jobs all ove two build steps:
    2 changes: 1 addition & 1 deletion 0-dependencies.json
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    "cookbooks": {
    "build-essential": {
    "url": "git://github.com/opscode-cookbooks/build-essential.git"
    "branch": "master",
    "branch": "master",
    "revision": "2991fc6e5448e5b2378eb6882e9c1ce557d828f0"
    },
    "cron": {
  12. Gavin M. Roy revised this gist Jul 29, 2013. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions 0-auto-manged-chef-repo.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    The files in this gist are for having Jenkins automatically manage a chef repository using git submodules. This allows for clean, clutter free management of individual cookbooks, and individual respositories for roles, environments and data bags.
  13. Gavin M. Roy revised this gist Jul 29, 2013. 2 changed files with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions 0-dependencies-json-notes.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    The `dependencies.json` file allows for more granularity than `metadata.rb`, specifying the remote repository and optionally the branch and revision to use. It should be placed in the root directory for each cookbook you create, but can be empty:

    {}
    Binary file modified 0-dependencies.json
    Binary file not shown.
  14. Gavin M. Roy revised this gist Jul 29, 2013. 1 changed file with 0 additions and 0 deletions.
    Binary file added 0-dependencies.json
    Binary file not shown.
  15. Gavin M. Roy revised this gist Jul 29, 2013. 5 changed files with 0 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
  16. Gavin M. Roy revised this gist Jul 29, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion cookbook-dependency.py
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@
    # per cookbook "Execute Python" build step *after* the cookbook-update.sh build
    # step

    import json
    import json
    import os
    import subprocess
    import sys
  17. Gavin M. Roy created this gist Jul 29, 2013.
    69 changes: 69 additions & 0 deletions cookbook-dependency.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    # This script processes the dependencies.json file in a cookbook and either adds
    # or updates the submodule information in the master repo, this is run in a job
    # per cookbook "Execute Python" build step *after* the cookbook-update.sh build
    # step

    import json
    import os
    import subprocess
    import sys

    base_path = os.environ['WORKSPACE'] + '/' + 'repo'

    cookbook = os.environ['JOB_NAME']
    cookbook_path = '%s/cookbooks/%s' % (base_path, cookbook)
    dependencies = '%s/dependencies.json' % cookbook_path


    def execute(command):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    if p.returncode:
    print 'Command failure [%s] returned %s' % (' '.join(command),
    p.returncode)
    print
    print stderr
    print
    sys.exit(p.returncode)
    return stdout

    os.chdir(base_path)
    if os.path.exists(dependencies):
    with open(dependencies, 'r') as handle:
    data = json.load(handle)

    cookbooks = data.get('cookbooks', dict())
    for name in cookbooks:
    print 'Processing dependency cookbook %s' % name
    dependency_path = '%s/cookbooks/%s' % (base_path, name)
    if not os.path.exists(dependency_path):
    print 'Adding dependency cookbook %s' % name
    execute(['git', 'submodule', 'add', cookbooks[name]['url'], 'cookbooks/%s' % name])
    print 'Committing addition of dependency cookbook %s' % name
    execute(['git', 'commit', '-m', 'Adding dependency cookbook %s' % name,
    '.gitmodules', 'cookbooks/%s' % name])

    print 'Updating dependency cookbook %s' % name
    execute(['git', 'submodule', 'update', '--init', 'cookbooks/%s' % name])

    os.chdir(dependency_path)
    if cookbooks[name].get('branch'):
    execute(['git', 'checkout', '-b', cookbooks[name].get('branch', 'master')])
    execute(['git', 'pull', '-f', '-u', 'origin', cookbooks[name].get('branch', 'master')])
    os.chdir(base_path)

    if 'revision' in cookbooks[name]:
    # Change to that revision
    os.chdir(dependency_path)
    execute(['git', 'reset', '--hard', cookbooks[name]['revision']])

    # Commit the specific revision for that cookbook
    os.chdir(base_path)
    stdout = execute(['git', 'status', '--porcelain'])
    if stdout:
    print 'Committing updates to dependency cookbook "%s"' % name
    revision = cookbooks[name].get('revision', 'HEAD')
    execute(['git', 'commit', '-m', 'Updating dependency cookbook %s to %s' % (name, revision),
    '.gitmodules', 'cookbooks/%s' % name])
    else:
    print 'No changes to commit for dependency cookbook %s' % name
    25 changes: 25 additions & 0 deletions cookbook-update.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    # This is the first build step for a cookbook repo update which is
    # triggered by a GitHub callback to Jenkins on commit

    # Reset the workspace, we don't want the git checkout of $JOB_NAME
    cd $WORKSPACE/..
    rm -rf workspace
    mkdir workspace
    cd workspace

    # Pull down repo
    git clone git@github.com:YOUR/chef-repo.git
    cd repo

    # Add or update the cookbook
    if [ ! -d "cookbooks/${JOB_NAME}" ]; then
    git submodule add $GIT_URL cookbooks/$JOB_NAME
    git submodule init cookbooks/$JOB_NAME
    git commit -m "Adding cookbook ${JOB_NAME}" .gitmodules cookbooks/$JOB_NAME
    else
    git submodule update --init cookbooks/$JOB_NAME
    cd cookbooks/$JOB_NAME
    git pull -f -u origin master
    cd ../..
    git commit -m "Updating cookbook ${JOB_NAME} to ${GIT_COMMIT}" .gitmodules cookbooks/$JOB_NAME
    fi
    11 changes: 11 additions & 0 deletions knife.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    # Goes in /var/lib/jenkins/.chef/
    log_level :info
    log_location STDOUT

    syntax_check_cache_path "#{ENV['HOME']}/.chef/syntax_check_cache"
    chef_server_url "#{ENV['KNIFE_CHEF_SERVER']}"
    client_key "#{ENV['KNIFE_CLIENT_KEY']}"
    node_name "#{ENV['KNIFE_NODE_NAME']}"
    validation_client_name "#{ENV['KNIFE_VALIDATION_CLIENT_NAME']}"
    validation_key "#{ENV['KNIFE_VALIDATION_CLIENT_KEY']}"
    cookbook_path "#{ENV['KNIFE_COOKBOOK_PATH']}"
    54 changes: 54 additions & 0 deletions knife_production_upload.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    # Used for the job that is notified when the master chef repository is updated when
    # a cookbook, role, environment or data bag repository updates chef-repo. When
    # cookbook-dependency.py, cookbook-update.sh or other-buid.sh are run, they will
    # update chef-repo and push the changes, causing GitHub to trigger Jenkins to run
    # the job with this shell script as its build step.

    # Update the submodules to the proper revisions
    git submodule update --init --recursive

    # Knife configuration
    export KNIFE_CHEF_SERVER="YOUR_CHEF_SERVER"
    export KNIFE_CLIENT_KEY="$HOME/.chef/client.pem"
    export KNIFE_NODE_NAME="jenkins"
    export KNIFE_VALIDATION_CLIENT_NAME="chef-validator"
    export KNIFE_VALIDATION_CLIENT_KEY="$HOME/.chef/validation.pem"
    export KNIFE_COOKBOOK_PATH=$WORKSPACE/cookbooks

    OBJECT=`git log --pretty=oneline -n 1 | perl -n -e '/^(\w{40})\s+(Adding|Updating)\s(cookbook|dependency\scookbook|environments|data_bags|roles)/ && {print "$3"}'`

    if [ "$OBJECT" == "cookbook" ] || [ "$OBJECT" == "dependency cookbook" ]; then

    # Extract the cookbook to upload
    COOKBOOK=`git log --pretty=oneline -n 1 | perl -n -e '/^\w{40}\s+((Adding|Updating)\sdependency\scookbook\s([\w-]+)\sto.*$|(Adding|Updating)\scookbook\s([\w-_]+)\sto.*$)/m && {print "$3$5\n"}'`

    # Upload the cookbook
    knife cookbook upload $COOKBOOK

    elif [ "$OBJECT" == "data_bags" ]; then
    cd $WORKSPACE/data_bags
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-\_]+\/[\w\-\_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for data_bag in $FILES
    do
    knife data bag from file ${data_bag/\// }
    done

    elif [ "$OBJECT" == "environments" ]; then
    cd $WORKSPACE/environments
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for environment in $FILES
    do
    knife environment from file $environment
    done

    elif [ "$OBJECT" == "roles" ]; then
    cd $WORKSPACE/roles
    FILES=`git log --pretty=oneline --name-only -n 1 | perl -n -e '/^([\w\-_]+\.json)$/m && {print "$1\n"}'`
    cd $WORKSPACE
    for role in FILES
    do
    knife role from file $f
    done
    fi
    23 changes: 23 additions & 0 deletions other-build.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    # This is the only build step for updates to the data bag, role and
    # environment repositories which are triggered by a GitHub callback
    # to Jenkins on commit

    # Reset the workspace, we don't want the git checkout of $JOB_NAME
    cd $WORKSPACE/..
    rm -rf workspace
    mkdir workspace
    cd workspace

    # Pull down repo
    git clone git@github.com:YOUR/chef-repo.git
    cd repo

    # Update the $JOB_NAME
    git submodule update --init $JOB_NAME
    cd $JOB_NAME
    git pull -f -u origin master
    cd ..
    git commit -m "Updating ${JOB_NAME} to ${GIT_COMMIT}" .gitmodules $JOB_NAME

    # Push the change
    git push origin master