Skip to content

Commit e86d9d8

Browse files
author
Matthew Fisher
committed
feat(builder): build apps from more than master
Previously, the builder would completely disregard any pushes from a branch other than master. This moves the builder command into a post-receive hook, such that we can reference the branch that is being pushed to the repository and send that to the builder. For some reason, this PR also gives us Heroku compatibility on issue #736, so this PR kills two birds with one stone. TESTING: To test, we need to successfully push an app from a branch other than master. To do that, run the following: $ make -C builder build restart $ cd /tmp $ git clone https://github.com/opdemand/example-perl && cd example-perl $ git checkout -b test-branch $ deis create $ git push deis test-branch To test for the #736 ninja fix, try pushing again. You should see a "Everything up-to-date" message displayed on your screen, and no push should occur. fixes #975, #736
1 parent 0728993 commit e86d9d8

2 files changed

Lines changed: 39 additions & 34 deletions

File tree

builder/templates/builder

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ import yaml
1717

1818

1919
def parse_args():
20-
if len(sys.argv) < 2:
21-
print('Usage: {} [user] [repo]'.format(sys.argv[0]))
20+
if len(sys.argv) < 3:
21+
print('Usage: {} [user] [repo] [branch]'.format(sys.argv[0]))
2222
sys.exit(1)
23-
user, repo = sys.argv[1], sys.argv[2]
23+
user, repo, branch = sys.argv[1], sys.argv[2], sys.argv[3]
2424
app = repo.split('.')[0]
25-
return user, repo, app
25+
return user, repo, branch, app
2626

2727

2828
DOCKERFILE_SHIM = """FROM deis/slugrunner
@@ -33,7 +33,7 @@ ENTRYPOINT ["/runner/init"]
3333

3434

3535
if __name__ == '__main__':
36-
user, repo, app = parse_args()
36+
user, repo, branch, app = parse_args()
3737
# define image names
3838
_id = uuid.uuid4().hex[:8]
3939
tmp_image = "{app}:temp_{_id}".format(**locals())
@@ -48,9 +48,9 @@ if __name__ == '__main__':
4848
try:
4949
# create temporary directory
5050
temp_dir = tempfile.mkdtemp(dir=build_dir)
51-
# extract git master
51+
# extract git branch
5252
p = subprocess.Popen(
53-
'git archive master | tar -x -C {temp_dir}'.format(**locals()),
53+
'git archive {branch} | tar -x -C {temp_dir}'.format(**locals()),
5454
shell=True, cwd=repo_dir)
5555
rc = p.wait()
5656
if rc != 0:
@@ -73,7 +73,7 @@ if __name__ == '__main__':
7373
else:
7474
build_cmd = "docker run -i -a stdin {config_env} -v {cache_dir}:/tmp/cache:rw deis/slugbuilder".format(**locals())
7575
# run slugbuilder in the background
76-
p = subprocess.Popen("git archive master | " + build_cmd, shell=True, cwd=repo_dir, stdout=subprocess.PIPE)
76+
p = subprocess.Popen("git archive {branch} | ".format(**locals()) + build_cmd, shell=True, cwd=repo_dir, stdout=subprocess.PIPE)
7777
container = p.stdout.read().strip('\n')
7878
# attach to slugbuilder output
7979
p = subprocess.Popen('docker attach {container}'.format(**locals()), shell=True, cwd=temp_dir)
@@ -114,8 +114,8 @@ if __name__ == '__main__':
114114
body['receive_user'] = user
115115
body['receive_repo'] = app
116116
body['image'] = target_image
117-
# use sha of master
118-
with open(os.path.join(repo_dir, 'refs/heads/master')) as f:
117+
# use sha of branch
118+
with open(os.path.join(repo_dir, branch)) as f:
119119
body['sha'] = f.read().strip('\n')
120120
# extract the user-defined Procfile and any default_process_types
121121
procfile_dict = {}

builder/templates/gitreceive

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ SELF=`which $0`
88
case "$1" in
99

1010
# called by sshd on each `git push`
11-
run)
11+
run)
1212
export RECEIVE_USER=$2
1313
export RECEIVE_FINGERPRINT=$3
1414
# ssh provides the original requested command in $SSH_ORIGINAL_COMMAND
@@ -22,43 +22,48 @@ case "$1" in
2222
fi
2323
cd $GITHOME
2424
PRERECEIVE_HOOK="$REPO_PATH/hooks/pre-receive"
25-
# inject the hook below
25+
# inject a pre-receive hook
2626
cat > $PRERECEIVE_HOOK <<EOF
2727
#!/bin/bash
28-
cat | $SELF hook
28+
cat | $SELF pre-receive
2929
EOF
3030
chmod +x $PRERECEIVE_HOOK
31+
POSTRECEIVE_HOOK="$REPO_PATH/hooks/post-receive"
32+
# inject a post-receive hook
33+
cat > $POSTRECEIVE_HOOK <<EOF
34+
#!/bin/bash
35+
cat | $SELF post-receive
36+
EOF
37+
chmod +x $POSTRECEIVE_HOOK
3138
git-shell -c "$SSH_ORIGINAL_COMMAND"
32-
# if we're processing a receive-pack on an existing repo, run a build
33-
if [[ $SSH_ORIGINAL_COMMAND == git-receive-pack* ]] && \
34-
[[ -e $REPO_PATH/refs/heads/master ]]; then
35-
# SECURITY: git user runs the builder as root (for docker access)
36-
sudo $GITHOME/builder $RECEIVE_USER $RECEIVE_REPO >&2
37-
fi
3839
;;
3940

40-
# used internally
41-
hook)
41+
pre-receive)
42+
while read oldrev newrev refname
43+
do
44+
$GITHOME/receiver "$RECEIVE_REPO" "$newrev" "$RECEIVE_USER" "$RECEIVE_FINGERPRINT"
45+
rc=$?
46+
if [[ $rc != 0 ]] ; then
47+
echo " ERROR: failed on rev $newrev - push denied"
48+
exit $rc
49+
fi
50+
done
51+
;;
52+
53+
post-receive)
4254
while read oldrev newrev refname
4355
do
44-
# Only run this script for the master branch. You can remove this
45-
# if block if you wish to run it for others as well.
46-
if [[ $refname = "refs/heads/master" ]] ; then
47-
48-
$GITHOME/receiver "$RECEIVE_REPO" "$newrev" "$RECEIVE_USER" "$RECEIVE_FINGERPRINT"
49-
50-
rc=$?
51-
if [[ $rc != 0 ]] ; then
52-
echo " ERROR: failed on rev $newrev - push denied"
53-
exit $rc
54-
fi
56+
# builder assumes that we are running this script from $GITHOME
57+
cd $GITHOME
58+
# if we're processing a receive-pack on an existing repo, run a build
59+
if [[ $SSH_ORIGINAL_COMMAND == git-receive-pack* ]]; then
60+
# SECURITY: git user runs the builder as root (for docker access)
61+
sudo $GITHOME/builder $RECEIVE_USER $RECEIVE_REPO $refname >&2
5562
fi
5663
done
57-
#exit 1 # for debugging
5864
;;
5965

6066
*)
6167
echo "Usage: gitreceive <command> [options]"
6268
;;
6369
esac
64-

0 commit comments

Comments
 (0)