summaryrefslogtreecommitdiffstats
path: root/tools/github-sync/sync-to-github.sh
blob: d6776497489607a90d1f2374357d37ae03fcee44 (plain)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env bash

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. */

# Do NOT set -x here, since that will expose a secret API token!
set -o errexit
set -o nounset
set -o pipefail

if [[ "$(uname)" != "Linux" ]]; then
    echo "Error: this script must be run on Linux due to readlink semantics"
    exit 1
fi

# GECKO_PATH should definitely be set
if [[ -z "${GECKO_PATH}" ]]; then
    echo "Error: GECKO_PATH must point to a hg clone of mozilla-central"
    exit 1
fi

# Internal variables, don't fiddle with these
MYSELF=$(readlink -f ${0})
MYDIR=$(dirname "${MYSELF}")
WORKDIR="${HOME}/.ghsync"
TMPDIR="${WORKDIR}/tmp"

NAME="$1"
RELATIVE_PATH="$2"
DOWNSTREAM_REPO="$3"
BORS="$4"
BRANCH="github-sync"

mkdir -p "${TMPDIR}"

# Bring the project clone to a known good up-to-date state
if [[ ! -d "${WORKDIR}/${NAME}" ]]; then
    echo "Setting up ${NAME} repo..."
    git clone "https://github.com/${DOWNSTREAM_REPO}" "${WORKDIR}/${NAME}"
    pushd "${WORKDIR}/${NAME}"
    git remote add moz-gfx https://github.com/moz-gfx/${NAME}
    popd
else
    echo "Updating ${NAME} repo..."
    pushd "${WORKDIR}/${NAME}"
    git checkout master
    git pull
    popd
fi

if [[ -n "${GITHUB_SECRET:-}" ]]; then
    echo "Obtaining github API token..."
    # Be careful, GITHUB_TOKEN is secret, so don't log it (or any variables
    # built using it).
    GITHUB_TOKEN=$(
        curl -sSfL "$TASKCLUSTER_PROXY_URL/secrets/v1/secret/${GITHUB_SECRET}" |
        ${MYDIR}/read-json.py "secret/token"
    )
    AUTH="moz-gfx:${GITHUB_TOKEN}"
    CURL_AUTH="Authorization: bearer ${GITHUB_TOKEN}"
fi

echo "Pushing base ${BRANCH} branch..."
pushd "${WORKDIR}/${NAME}"
git fetch moz-gfx
git checkout -B ${BRANCH} moz-gfx/${BRANCH} || git checkout -B ${BRANCH} master

if [[ -n "${GITHUB_SECRET:-}" ]]; then
    # git may emit error messages that contain the URL, so let's sanitize them
    # or we might leak the auth token to the task log.
    git push "https://${AUTH}@github.com/moz-gfx/${NAME}" \
        "${BRANCH}:${BRANCH}" 2>&1 | sed -e "s/${AUTH}/_SANITIZED_/g"
    # Re-fetch to update the remote moz-gfx/$BRANCH branch in the local repo;
    # normally the push does this but we use a fully-qualified URL for
    # pushing so it doesn't happen.
    git fetch moz-gfx
fi
popd

# Run the converter
echo "Running converter..."
pushd "${GECKO_PATH}"
"${MYDIR}/converter.py" "${WORKDIR}/${NAME}" "${RELATIVE_PATH}"
popd

# Check to see if we have changes that need pushing
echo "Checking for new changes..."
pushd "${WORKDIR}/${NAME}"
PATCHCOUNT=$(git log --oneline moz-gfx/${BRANCH}..${BRANCH}| wc -l)
if [[ ${PATCHCOUNT} -eq 0 ]]; then
    echo "No new patches found, aborting..."
    exit 0
fi

# Log the new changes, just for logging purposes
echo "Here are the new changes:"
git log --graph --stat moz-gfx/${BRANCH}..${BRANCH}

# Collect PR numbers of PRs opened on Github and merged to m-c
set +e
FIXES=$(
    git log master..${BRANCH} |
    grep "\[import_pr\] From https://github.com/${DOWNSTREAM_REPO}/pull" |
    sed -e "s%.*pull/% Fixes #%" |
    uniq |
    tr '\n' ','
)
echo "${FIXES}"
set -e

if [[ -z "${GITHUB_SECRET:-}" ]]; then
    echo "Running in try push, exiting now"
    exit 0
fi

echo "Pushing new changes to moz-gfx..."
# git may emit error messages that contain the URL, so let's sanitize them
# or we might leak the auth token to the task log.
git push "https://${AUTH}@github.com/moz-gfx/${NAME}" +${BRANCH}:${BRANCH} \
    2>&1 | sed -e "s/${AUTH}/_SANITIZED_/g"

CURL_HEADER="Accept: application/vnd.github.v3+json"
CURL=(curl -sSfL -H "${CURL_HEADER}" -H "${CURL_AUTH}")
# URL extracted here mostly to make servo-tidy happy with line lengths
API_URL="https://api.github.com/repos/${DOWNSTREAM_REPO}"

# Check if there's an existing PR open
echo "Listing pre-existing pull requests..."
"${CURL[@]}" "${API_URL}/pulls?head=moz-gfx:${BRANCH}" |
    tee "${TMPDIR}/pr.get"
set +e
COMMENT_URL=$(cat "${TMPDIR}/pr.get" | ${MYDIR}/read-json.py "0/comments_url")
HAS_COMMENT_URL="${?}"
set -e

if [[ ${HAS_COMMENT_URL} -ne 0 ]]; then
    echo "Pull request not found, creating..."
    # The PR doesn't exist yet, so let's create it
    (   echo -n '{ "title": "Sync changes from mozilla-central '"${RELATIVE_PATH}"'"'
        echo -n ', "body": "'"${FIXES}"'"'
        echo -n ', "head": "moz-gfx:'"${BRANCH}"'"'
        echo -n ', "base": "master" }'
    ) > "${TMPDIR}/pr.create"
    "${CURL[@]}" -d "@${TMPDIR}/pr.create" "${API_URL}/pulls" |
        tee "${TMPDIR}/pr.response"
    COMMENT_URL=$(
        cat "${TMPDIR}/pr.response" |
        ${MYDIR}/read-json.py "comments_url"
    )
fi

# At this point COMMENTS_URL should be set, so leave a comment to tell bors
# to merge the PR.
echo "Posting r+ comment to ${COMMENT_URL}..."
echo '{ "body": "'"$BORS"' r=auto" }' > "${TMPDIR}/bors_rplus"
"${CURL[@]}" -d "@${TMPDIR}/bors_rplus" "${COMMENT_URL}"

echo "All done!"