blob: 9fe605077b5d3a73768de9a966107203b77bbb28 [file] [log] [blame]
#!/bin/bash
function usage {
cat <<EOF
Usage: `basename $0` -h # Displays this usage/help text
Usage: `basename $0` -x # lists exit codes
Usage: `basename $0` [-n] [-c] [-d] [-a]
[-p product]
[--hgtool hgtool_location]
[--mirror hg_mirror --bundle bundle_location]
[-u hg_ssh_user]
[-k hg_ssh_key]
[-r existing_repo_dir]
# Use mozilla-central builds to check HSTS & HPKP
[--use-mozilla-central]
# One (or more) of the following actions must be specified.
--hsts | --hpkp | --blocklist
-b branch
EOF
}
function exitcodes {
cat <<EOF
EXIT CODES for `basename $0`:
0 Success (either no updates to push, or push was successful)
2 Updates are available, but were not pushed due to dry-run mode.
11 Unknown command-line option provided
12 Branch not specified on command-line
13 No update action specified on command-line
14 Invalid product specified
21 Unable to parse version from version.txt
31 Missing downloaded browser artifact
32 Missing downloaded tests artifact
41 Missing downloaded HSTS file
42 Generated HSTS preload list is empty
51 Missing downloaded HPKP file
52 Generated HPKP preload list is empty
61 Downloaded AMO blocklist file isn't valid XML
62 Downloaded hg blocklist file isn't valid XML
70 HSTS script failed
71 HPKP script failed
EOF
}
DRY_RUN=false
PRODUCT="firefox"
BRANCH=""
PLATFORM="linux-x86_64"
TBOX_BUILDS_PLATFORM="linux64"
PLATFORM_EXT="tar.bz2"
UNPACK_CMD="tar jxf"
CLOSED_TREE=false
DONTBUILD=false
APPROVAL=false
HG_SSH_USER='ffxbld'
HG_SSH_KEY='~cltbld/.ssh/ffxbld_rsa'
REPODIR=''
HGTOOL="$(dirname "${0}")/../../buildfarm/utils/hgtool.py"
MIRROR=''
BUNDLE=''
APP_DIR=''
APP_ID=''
APP_NAME=''
LOCALHOST=`/bin/hostname -s`
HGHOST="hg.mozilla.org"
STAGEHOST="stage.mozilla.org"
HG=hg
WGET="wget -nv"
UNZIP="unzip -q"
DIFF="diff -up"
BASEDIR=`pwd`
SCRIPTDIR=`dirname $0`
VERSION=''
MCVERSION=''
USE_MC=false
FLATTENED=true
DO_HSTS=false
HSTS_PRELOAD_SCRIPT="getHSTSPreloadList.js"
HSTS_PRELOAD_ERRORS="nsSTSPreloadList.errors"
HSTS_PRELOAD_INC="nsSTSPreloadList.inc"
HSTS_UPDATED=false
DO_HPKP=false
HPKP_PRELOAD_SCRIPT="genHPKPStaticPins.js"
HPKP_PRELOAD_ERRORS="StaticHPKPins.errors"
HPKP_DER_TEST="default-ee.der"
HPKP_PRELOAD_JSON="PreloadedHPKPins.json"
HPKP_PRELOAD_OUTPUT="StaticHPKPins.h"
HPKP_UPDATED=false
DO_BLOCKLIST=false
BLOCKLIST_URL_AMO=''
BLOCKLIST_URL_HG=''
BLOCKLIST_UPDATED=false
# Get the current in-tree version for a code branch.
function get_version {
VERSION_REPO=$1
VERSION_FILE='version.txt'
cd "${BASEDIR}"
VERSION_URL_HG="${VERSION_REPO}/raw-file/default/${APP_DIR}/config/version.txt"
rm -f ${VERSION_FILE}
${WGET} --no-check-certificate -O ${VERSION_FILE} ${VERSION_URL_HG}
WGET_STATUS=$?
if [ ${WGET_STATUS} != 0 ]; then
echo "ERROR: wget exited with a non-zero exit code: $WGET_STATUS" >&2
exit ${WGET_STATUS}
fi
PARSED_VERSION=`cat version.txt`
if [ "${PARSED_VERSION}" == "" ]; then
echo "ERROR: Unable to parse version from $VERSION_FILE" >&2
exit 21
fi
rm -f ${VERSION_FILE}
echo ${PARSED_VERSION}
}
# Cleanup common artifacts.
function preflight_cleanup {
cd "${BASEDIR}"
rm -rf "${PRODUCT}" tests "${BROWSER_ARCHIVE}" "${TESTS_ARCHIVE}"
}
function download_shared_artifacts {
cd "${BASEDIR}"
# Download everything we need: browser, tests, updater script, existing preload list and errors.
echo "INFO: Downloading all the necessary pieces..."
POSSIBLE_ARTIFACT_DIRS="nightly/latest-${REPODIR} tinderbox-builds/${REPODIR}-${TBOX_BUILDS_PLATFORM}/latest"
if [ "${USE_MC}" == "true" ]; then
POSSIBLE_ARTIFACT_DIRS="nightly/latest-mozilla-central"
fi
for ARTIFACT_DIR in ${POSSIBLE_ARTIFACT_DIRS}; do
BROWSER_ARCHIVE_URL="http://${STAGEHOST}/pub/mozilla.org/${PRODUCT}/${ARTIFACT_DIR}/${BROWSER_ARCHIVE}"
TESTS_ARCHIVE_URL="http://${STAGEHOST}/pub/mozilla.org/${PRODUCT}/${ARTIFACT_DIR}/${TESTS_ARCHIVE}"
echo "INFO: ${WGET} --no-check-certificate ${BROWSER_ARCHIVE_URL}"
${WGET} --no-check-certificate ${BROWSER_ARCHIVE_URL}
echo "INFO: ${WGET} --no-check-certificate ${TESTS_ARCHIVE_URL}"
${WGET} --no-check-certificate ${TESTS_ARCHIVE_URL}
if [ -f ${BROWSER_ARCHIVE} -a -f ${TESTS_ARCHIVE} ]; then
break
fi
done
if [ ! -f ${BROWSER_ARCHIVE} ]; then
echo "Downloaded file '${BROWSER_ARCHIVE}' not found in directory '$(pwd)'." >&2
exit 31
fi
if [ ! -f ${TESTS_ARCHIVE} ]; then
echo "Downloaded file '${TESTS_ARCHIVE}' not found in directory '$(pwd)'." >&2
exit 32
fi
# Unpack the browser and move xpcshell in place for updating the preload list.
echo "INFO: Unpacking resources..."
${UNPACK_CMD} "${BROWSER_ARCHIVE}"
mkdir tests && cd tests
${UNZIP} "../${TESTS_ARCHIVE}"
cd "${BASEDIR}"
cp tests/bin/xpcshell "${PRODUCT}"
}
# gtk3 is required to run xpcshell as of Gecko 42.
function download_gtk3 {
sh ${SCRIPTDIR}/../tooltool/tooltool_wrapper.sh ${SCRIPTDIR}/periodic_file_updates.manifest https://api.pub.build.mozilla.org/tooltool/ setup.sh /builds/tooltool.py --authentication-file /builds/relengapi.tok
LD_LIBRARY_PATH=${BASEDIR}/gtk3/usr/local/lib
}
# In bug 1164714, the public/src subdirectories were flattened away under security/manager.
# We need to check whether the HGREPO were processing has had that change uplifted yet so
# that we can find the files we need to update.
function is_flattened {
# This URL will only be present in repos that have *not* been flattened.
TEST_URL="${HGREPO}/raw-file/default/security/manager/boot/src/"
HTTP_STATUS=`${WGET} --spider -S ${TEST_URL} 2>&1 | grep "HTTP/" | awk '{print $2}'`
if [ "$HTTP_STATUS" == "200" ]; then
export FLATTENED=false
fi
}
# Downloads the current in-tree HSTS (HTTP Strict Transport Security) files.
# Runs a simple xpcshell script to generate up-to-date HSTS information.
# Compares the new HSTS output with the old to determine whether we need to update.
function compare_hsts_files {
cd "${BASEDIR}"
HSTS_PRELOAD_SCRIPT_HG="${HGREPO}/raw-file/default/security/manager/tools/${HSTS_PRELOAD_SCRIPT}"
if [ "${FLATTENED}" == "true" ]; then
HSTS_PRELOAD_ERRORS_HG="${HGREPO}/raw-file/default/security/manager/ssl/${HSTS_PRELOAD_ERRORS}"
HSTS_PRELOAD_INC_HG="${HGREPO}/raw-file/default/security/manager/ssl/${HSTS_PRELOAD_INC}"
else
HSTS_PRELOAD_ERRORS_HG="${HGREPO}/raw-file/default/security/manager/boot/src/${HSTS_PRELOAD_ERRORS}"
HSTS_PRELOAD_INC_HG="${HGREPO}/raw-file/default/security/manager/boot/src/${HSTS_PRELOAD_INC}"
fi
# Download everything we need: browser, tests, updater script, existing preload list and errors.
echo "INFO: Downloading all the necessary pieces to update HSTS..."
rm -rf "${HSTS_PRELOAD_SCRIPT}" "${HSTS_PRELOAD_ERRORS}" "${HSTS_PRELOAD_INC}"
for URL in "${HSTS_PRELOAD_SCRIPT_HG}" "${HSTS_PRELOAD_ERRORS_HG}" "${HSTS_PRELOAD_INC_HG}"; do
echo "INFO: ${WGET} --no-check-certificate ${URL}"
${WGET} --no-check-certificate ${URL}
WGET_STATUS=$?
if [ ${WGET_STATUS} != 0 ]; then
echo "ERROR: wget exited with a non-zero exit code: ${WGET_STATUS}" >&2
exit ${WGET_STATUS}
fi
if [ ! -f "$(basename "${URL}")" ]; then
echo "Downloaded file '$(basename "${URL}")' not found in directory '$(pwd)' - this should have been downloaded above from ${URL}." >&2
exit 41
fi
done
# Run the script to get an updated preload list.
echo "INFO: Generating new HSTS preload list..."
cd "${BASEDIR}/${PRODUCT}"
echo INFO: Running \"LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./xpcshell ${BASEDIR}/${HSTS_PRELOAD_SCRIPT} ${BASEDIR}/${HSTS_PRELOAD_INC}\"
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./xpcshell "${BASEDIR}/${HSTS_PRELOAD_SCRIPT}" "${BASEDIR}/${HSTS_PRELOAD_INC}"
XPCSHELL_STATUS=$?
if [ ${XPCSHELL_STATUS} != 0 ]; then
cat ${HSTS_PRELOAD_ERRORS}
echo "ERROR: xpcshell exited with a non-zero exit code: ${XPCSHELL_STATUS}" >&2
exit 70
fi
# The created files should be non-empty.
echo "INFO: Checking whether new HSTS preload list is valid..."
if [ ! -s "${HSTS_PRELOAD_ERRORS}" ]; then
echo "New HSTS preload error list ${HSTS_PRELOAD_ERRORS} is empty. I guess that's good?" >&2
fi
if [ ! -s "${HSTS_PRELOAD_INC}" ]; then
echo "New HSTS preload list ${HSTS_PRELOAD_INC} is empty. That's less good." >&2
exit 42
fi
cd "${BASEDIR}"
# Check for differences
echo "INFO: diffing old/new HSTS error lists..."
${DIFF} "${HSTS_PRELOAD_ERRORS}" "${PRODUCT}/${HSTS_PRELOAD_ERRORS}"
DIFF_STATUS=$?
case "${DIFF_STATUS}" in
0) echo "INFO: New HSTS preload error list matches what is in-tree.";;
1) echo "INFO: New HSTS preload error list differs from what is in-tree.";;
*) echo "ERROR: diff exited with exit code: ${DIFF_STATUS}" >&2
exit ${DIFF_STATUS}
esac
echo "INFO: diffing old/new HSTS preload lists..."
${DIFF} "${HSTS_PRELOAD_INC}" "${PRODUCT}/${HSTS_PRELOAD_INC}"
DIFF_STATUS=$?
case "${DIFF_STATUS}" in
0) echo "INFO: New HSTS preload list matches what is in-tree.";;
1) echo "INFO: New HSTS preload list differs from what is in-tree.";;
*) echo "ERROR: diff exited with exit code: ${DIFF_STATUS}" >&2
exit ${DIFF_STATUS}
esac
return ${DIFF_STATUS}
}
# Downloads the current in-tree HPKP (HTTP public key pinning) files.
# Runs a simple xpcshell script to generate up-to-date HPKP information.
# Compares the new HPKP output with the old to determine whether we need to update.
function compare_hpkp_files {
cd "${BASEDIR}"
HPKP_PRELOAD_SCRIPT_HG="${HGREPO}/raw-file/default/security/manager/tools/${HPKP_PRELOAD_SCRIPT}"
HPKP_PRELOAD_JSON_HG="${HGREPO}/raw-file/default/security/manager/tools/${HPKP_PRELOAD_JSON}"
HPKP_DER_TEST_HG="${HGREPO}/raw-file/default/security/manager/ssl/tests/unit/tlsserver/${HPKP_DER_TEST}"
if [ "${FLATTENED}" == "true" ]; then
HPKP_PRELOAD_ERRORS_HG="${HGREPO}/raw-file/default/security/manager/ssl/${HPKP_PRELOAD_ERRORS}"
HPKP_PRELOAD_OUTPUT_HG="${HGREPO}/raw-file/default/security/manager/ssl/${HPKP_PRELOAD_OUTPUT}"
else
HPKP_PRELOAD_ERRORS_HG="${HGREPO}/raw-file/default/security/manager/boot/src/${HPKP_PRELOAD_ERRORS}"
HPKP_PRELOAD_OUTPUT_HG="${HGREPO}/raw-file/default/security/manager/boot/src/${HPKP_PRELOAD_OUTPUT}"
fi
# Download everything we need: browser, tests, updater script, existing preload list and errors.
echo "INFO: Downloading all the necessary pieces to update HPKP..."
rm -f "${HPKP_PRELOAD_SCRIPT}" "${HPKP_PRELOAD_JSON}" "${HPKP_DER_TEST}" "${HPKP_PRELOAD_OUTPUT}" "${HPKP_PRELOAD_ERRORS}"
for URL in "${HPKP_PRELOAD_SCRIPT_HG}" "${HPKP_PRELOAD_JSON_HG}" "${HPKP_DER_TEST_HG}" "${HPKP_PRELOAD_OUTPUT_HG}" "${HPKP_PRELOAD_ERRORS_HG}"; do
echo "INFO: ${WGET} --no-check-certificate ${URL}"
${WGET} --no-check-certificate ${URL}
WGET_STATUS=$?
if [ ${WGET_STATUS} != 0 ]; then
echo "ERROR: wget exited with a non-zero exit code: ${WGET_STATUS}" >&2
exit ${WGET_STATUS}
fi
if [ ! -f "$(basename "${URL}")" ]; then
echo "Downloaded file '$(basename "${URL}")' not found in directory '$(pwd)' - this should have been downloaded above from ${URL}." >&2
exit 51
fi
done
# Run the script to get an updated preload list.
echo "INFO: Generating new HPKP preload list..."
cd "${BASEDIR}/${PRODUCT}"
echo INFO: Running \"LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./xpcshell ${BASEDIR}/${HPKP_PRELOAD_SCRIPT} ${BASEDIR}/${HPKP_PRELOAD_JSON} ${BASEDIR}/${HPKP_DER_TEST} ${BASEDIR}/${PRODUCT}/${HPKP_PRELOAD_OUTPUT}\"
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./xpcshell "${BASEDIR}/${HPKP_PRELOAD_SCRIPT}" "${BASEDIR}/${HPKP_PRELOAD_JSON}" "${BASEDIR}/${HPKP_DER_TEST}" "${BASEDIR}/${PRODUCT}/${HPKP_PRELOAD_OUTPUT}" > "${HPKP_PRELOAD_ERRORS}" 2>&1
XPCSHELL_STATUS=$?
if [ ${XPCSHELL_STATUS} != 0 ]; then
cat ${HPKP_PRELOAD_ERRORS}
echo "ERROR: xpcshell exited with a non-zero exit code: ${XPCSHELL_STATUS}" >&2
exit 71
fi
# The created files should be non-empty.
echo "INFO: Checking whether new HPKP preload list is valid..."
if [ ! -s "${HPKP_PRELOAD_ERRORS}" ]; then
echo "New ${HPKP_PRELOAD_ERRORS} error list is empty. I guess that's good?" >&2
fi
if [ ! -s "${HPKP_PRELOAD_OUTPUT}" ]; then
echo "${HPKP_PRELOAD_OUTPUT} is empty. That's less good." >&2
exit 52
fi
cd "${BASEDIR}"
# Check for differences
echo "INFO: diffing old/new HPKP error lists..."
${DIFF} "${HPKP_PRELOAD_ERRORS}" "${PRODUCT}/${HPKP_PRELOAD_ERRORS}"
DIFF_STATUS=$?
case "${DIFF_STATUS}" in
0) echo "INFO: New HPKP preload error matches what is in-tree.";;
1) echo "INFO: New HPKP preload error lists differs from what is in-tree.";;
*) echo "ERROR: diff exited with exit code: ${DIFF_STATUS}" >&2
exit ${DIFF_STATUS}
esac
echo "INFO: diffing old/new HPKP preload lists..."
${DIFF} "${HPKP_PRELOAD_OUTPUT}" "${PRODUCT}/${HPKP_PRELOAD_OUTPUT}"
DIFF_STATUS=$?
case "${DIFF_STATUS}" in
0) echo "INFO: New HPKP preload lists matches what is in-tree.";;
1) echo "INFO: New HPKP preload lists differs from what is in-tree.";;
*) echo "ERROR: diff exited with exit code: ${DIFF_STATUS}" >&2
exit ${DIFF_STATUS}
esac
return ${DIFF_STATUS}
}
# Downloads the current in-tree blocklist file.
# Downloads the current blocklist file from AMO.
# Compares the AMO blocklist with the in-tree blocklist to determine whether we need to update.
function compare_blocklist_files {
BLOCKLIST_URL_AMO="https://blocklist.addons.mozilla.org/blocklist/3/${APP_ID}/${VERSION}/${APP_NAME}/20090105024647/blocklist-sync/en-US/nightly/blocklist-sync/default/default/"
BLOCKLIST_URL_HG="${HGREPO}/raw-file/default/${APP_DIR}/app/blocklist.xml"
cd "${BASEDIR}"
rm -f blocklist_amo.xml
echo "INFO: ${WGET} --no-check-certificate -O blocklist_amo.xml ${BLOCKLIST_URL_AMO}"
${WGET} --no-check-certificate -O blocklist_amo.xml ${BLOCKLIST_URL_AMO}
WGET_STATUS=$?
if [ ${WGET_STATUS} != 0 ]; then
echo "ERROR: wget exited with a non-zero exit code: ${WGET_STATUS}"
exit ${WGET_STATUS}
fi
rm -f blocklist_hg.xml
echo "INFO: ${WGET} -O blocklist_hg.xml ${BLOCKLIST_URL_HG}"
${WGET} -O blocklist_hg.xml ${BLOCKLIST_URL_HG}
WGET_STATUS=$?
if [ ${WGET_STATUS} != 0 ]; then
echo "ERROR: wget exited with a non-zero exit code: ${WGET_STATUS}" >&2
exit ${WGET_STATUS}
fi
# The downloaded files should be non-empty and have a valid xml header
# if they were retrieved properly, and some random HTML garbage if not.
XML_HEADER='<?xml version="1.0"?>'
AMO_HEADER=`head -n1 blocklist_amo.xml`
HG_HEADER=`head -n1 blocklist_hg.xml`
if [ ! -s "blocklist_amo.xml" -o "${XML_HEADER}" != "${AMO_HEADER}" ]; then
echo "AMO blocklist does not appear to be an XML file. wget error?" >&2
exit 61
fi
if [ ! -s "blocklist_hg.xml" -o "${XML_HEADER}" != "${HG_HEADER}" ]; then
echo "HG blocklist does not appear to be an XML file. wget error?" >&2
exit 62
fi
echo "INFO: diffing in-tree blocklist against the blocklist from AMO..."
${DIFF} blocklist_hg.xml blocklist_amo.xml >/dev/null 2>&1
DIFF_STATUS=$?
case "${DIFF_STATUS}" in
0) echo "INFO: AMO blocklist is identical to the one in-tree.";;
1) echo "INFO: AMO blocklist differs from the one in-tree.";;
*) echo "ERROR: diff exited with exit code: ${DIFF_STATUS}" >&2
exit ${DIFF_STATUS}
esac
return ${DIFF_STATUS}
}
# Clones an hg repo, using hgtool preferentially.
function clone_repo {
cd "${BASEDIR}"
if [ ! -d "${REPODIR}" ]; then
CLONE_CMD=""
if [ -f "${HGTOOL}" ]; then
# Need to pass the default branch here to avoid pollution from buildprops.json
# when hgtool.py is run in production.
CLONE_CMD="${HGTOOL} --branch default"
if [ "${MIRROR}" != "" ]; then
CLONE_CMD="${CLONE_CMD} --mirror ${MIRROR}"
fi
if [ "${BUNDLE}" != "" ]; then
CLONE_CMD="${CLONE_CMD} --bundle ${BUNDLE}"
fi
else
# Fallback on vanilla hg
echo "INFO: hgtool.py not found. Falling back to vanilla hg."
CLONE_CMD="${HG} clone"
fi
CLONE_CMD="${CLONE_CMD} ${HGREPO} ${REPODIR}"
echo "INFO: cloning from hg: ${CLONE_CMD}"
${CLONE_CMD}
CLONE_STATUS=$?
if [ ${CLONE_STATUS} != 0 ]; then
echo "ERROR: hg clone exited with a non-zero exit code: ${CLONE_STATUS}" >&2
exit ${CLONE_STATUS}
fi
fi
echo "INFO: pulling from hg: ${HG} -R ${REPODIR} pull"
${HG} -R ${REPODIR} pull
PULL_STATUS=$?
if [ ${PULL_STATUS} != 0 ]; then
echo "ERROR: hg pull exited with a non-zero exit code: ${PULL_STATUS}" >&2
exit ${PULL_STATUS}
fi
echo "INFO: updating to default: ${HG} -R ${REPODIR} update -C default"
${HG} -R ${REPODIR} update -C default
UPDATE_STATUS=$?
if [ ${UPDATE_STATUS} != 0 ]; then
echo "ERROR: hg update exited with a non-zero exit code: ${UPDATE_STATUS}" >&2
exit ${UPDATE_STATUS}
fi
}
# Copies new HSTS files in place, and commits them.
function commit_hsts_files {
cd "${BASEDIR}"
if [ "${FLATTENED}" == "true" ]; then
cp -f ${PRODUCT}/${HSTS_PRELOAD_ERRORS} ${REPODIR}/security/manager/ssl/
cp -f ${PRODUCT}/${HSTS_PRELOAD_INC} ${REPODIR}/security/manager/ssl/
else
cp -f ${PRODUCT}/${HSTS_PRELOAD_ERRORS} ${REPODIR}/security/manager/boot/src/
cp -f ${PRODUCT}/${HSTS_PRELOAD_INC} ${REPODIR}/security/manager/boot/src/
fi
COMMIT_MESSAGE="No bug, Automated HSTS preload list update from host ${LOCALHOST}"
if [ ${DONTBUILD} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - (DONTBUILD)"
fi
if [ ${CLOSED_TREE} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - CLOSED TREE"
fi
if [ ${APPROVAL} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - a=hsts-update"
fi
echo "INFO: committing HSTS changes: ${HG} -R ${REPODIR} commit -u \"${HG_SSH_USER}\" -m \"${COMMIT_MESSAGE}\""
${HG} -R ${REPODIR} commit -u "${HG_SSH_USER}" -m "${COMMIT_MESSAGE}"
COMMIT_STATUS=$?
if [ ${COMMIT_STATUS} == 0 ]; then
echo "INFO: hg commit succeeded for HSTS files."
fi
return ${COMMIT_STATUS}
}
# Copies new HPKP files in place, and commits them.
function commit_hpkp_files {
cd "${BASEDIR}"
if [ "${FLATTENED}" == "true" ]; then
cp -f ${PRODUCT}/${HPKP_PRELOAD_ERRORS} ${REPODIR}/security/manager/ssl/
cp -f ${PRODUCT}/${HPKP_PRELOAD_OUTPUT} ${REPODIR}/security/manager/ssl/
else
cp -f ${PRODUCT}/${HPKP_PRELOAD_ERRORS} ${REPODIR}/security/manager/boot/src/
cp -f ${PRODUCT}/${HPKP_PRELOAD_OUTPUT} ${REPODIR}/security/manager/boot/src/
fi
COMMIT_MESSAGE="No bug, Automated HPKP preload list update from host ${LOCALHOST}"
if [ ${DONTBUILD} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - (DONTBUILD)"
fi
if [ ${CLOSED_TREE} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - CLOSED TREE"
fi
if [ ${APPROVAL} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - a=hpkp-update"
fi
echo "INFO: committing HPKP changes: ${HG} -R ${REPODIR} commit -u \"${HG_SSH_USER}\" -m \"${COMMIT_MESSAGE}\""
${HG} -R ${REPODIR} commit -u "${HG_SSH_USER}" -m "${COMMIT_MESSAGE}"
COMMIT_STATUS=$?
if [ ${COMMIT_STATUS} == 0 ]; then
echo "INFO: hg commit succeeded for HPKP files."
fi
return ${COMMIT_STATUS}
}
# Copies new blocklist file in place, and commits it.
function commit_blocklist_files {
cd "${BASEDIR}"
cp -f blocklist_amo.xml ${REPODIR}/${APP_DIR}/app/blocklist.xml
COMMIT_MESSAGE="No bug, Automated blocklist update from host ${LOCALHOST}"
if [ ${DONTBUILD} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - (DONTBUILD)"
fi
if [ ${CLOSED_TREE} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - CLOSED TREE"
fi
if [ ${APPROVAL} == true ]; then
COMMIT_MESSAGE="${COMMIT_MESSAGE} - a=blocklist-update"
fi
echo "INFO: committing blocklist changes: ${HG} -R ${REPODIR} commit -u \"${HG_SSH_USER}\" -m \"${COMMIT_MESSAGE}\""
${HG} -R ${REPODIR} commit -u "${HG_SSH_USER}" -m "${COMMIT_MESSAGE}"
COMMIT_STATUS=$?
if [ ${COMMIT_STATUS} == 0 ]; then
echo "INFO: hg commit succeeded for blocklist files."
fi
return ${COMMIT_STATUS}
}
# Push all pending commits to hg.
function push_repo {
cd "${BASEDIR}"
echo ${HG} -R ${REPODIR} push -e \"ssh -l ${HG_SSH_USER} -i ${HG_SSH_KEY}\" ${HGPUSHREPO}
${HG} -R ${REPODIR} push -e "ssh -l ${HG_SSH_USER} -i ${HG_SSH_KEY}" ${HGPUSHREPO}
PUSH_STATUS=$?
if [ ${PUSH_STATUS} != 0 ]; then
echo "ERROR: hg push exited with exit code: ${PUSH_STATUS}, probably raced another changeset"
echo ${HG} -R ${REPODIR} rollback
${HG} -R ${REPODIR} rollback
ROLLBACK_STATUS=$?
if [ ${ROLLBACK_STATUS} != 0 ]; then
echo "ERROR: hg rollback failed with exit code: ${ROLLBACK_STATUS}" >&2
echo "This is unrecoverable, removing the local clone to start fresh next time." >&2
rm -rf ${REPODIR}
exit ${ROLLBACK_STATUS}
fi
else
echo "INFO: hg push succeeded."
fi
return ${PUSH_STATUS}
}
# Main
# Parse our command-line options.
while [ $# -gt 0 ]; do
case "$1" in
-h) usage; exit 0;;
-x) exitcodes; exit 0;;
-p) PRODUCT="$2"; shift;;
-b) BRANCH="$2"; shift;;
-n) DRY_RUN=true;;
-c) CLOSED_TREE=true;;
-d) DONTBUILD=true;;
-a) APPROVAL=true;;
--hsts) DO_HSTS=true;;
--hpkp) DO_HPKP=true;;
--blocklist) DO_BLOCKLIST=true;;
-u) HG_SSH_USER="$2"; shift;;
-k) HG_SSH_KEY="$2"; shift;;
-r) REPODIR="$2"; shift;;
--mirror) MIRROR="$2"; shift;;
--bundle) BUNDLE="$2"; shift;;
--use-mozilla-central) USE_MC=true;;
-*) usage
exit 11;;
*) break;; # terminate while loop
esac
shift
done
# Must supply a code branch to work with.
if [ "${BRANCH}" == "" ]; then
echo "Error: You must specify a branch with -b branchname." >&2
usage
exit 12
fi
# Must choose at least one update action.
if [ "$DO_HSTS" == "false" -a "$DO_HPKP" == "false" -a "$DO_BLOCKLIST" == "false" ]; then
echo "Error: you must specify at least one action from: --hsts, --hpkp, --blocklist" >&2
usage
exit 13
fi
# per-product constants
case "${PRODUCT}" in
thunderbird)
APP_DIR="mail"
APP_ID="%7B3550f703-e582-4d05-9a08-453d09bdfdc6%7D"
APP_NAME="Thunderbird"
;;
firefox)
APP_DIR="browser"
APP_ID="%7Bec8030f7-c20a-464f-9b0e-13a3a9e97384%7D"
APP_NAME="Firefox"
;;
*)
echo "Error: Invalid product specified"
usage
exit 14
;;
esac
if [ "${REPODIR}" == "" ]; then
REPODIR=`basename ${BRANCH}`
fi
HGREPO="http://${HGHOST}/${BRANCH}"
HGPUSHREPO="ssh://${HGHOST}/${BRANCH}"
MCREPO="http://${HGHOST}/mozilla-central"
VERSION=$(get_version ${HGREPO})
echo "INFO: parsed version is ${VERSION}"
if [ "${USE_MC}" == "true" ]; then
MCVERSION=$(get_version ${MCREPO})
echo "INFO: parsed mozilla-central version is ${MCVERSION}"
fi
BROWSER_ARCHIVE="${PRODUCT}-${VERSION}.en-US.${PLATFORM}.${PLATFORM_EXT}"
TESTS_ARCHIVE="${PRODUCT}-${VERSION}.en-US.${PLATFORM}.common.tests.zip"
if [ "${USE_MC}" == "true" ]; then
BROWSER_ARCHIVE="${PRODUCT}-${MCVERSION}.en-US.${PLATFORM}.${PLATFORM_EXT}"
TESTS_ARCHIVE="${PRODUCT}-${MCVERSION}.en-US.${PLATFORM}.common.tests.zip"
fi
# Try to find hgtool if it hasn't been set.
if [ ! -f "${HGTOOL}" ]; then
HGTOOL=`which hgtool.py 2>/dev/null | head -n1`
fi
preflight_cleanup
if [ "${DO_HSTS}" == "true" -o "${DO_HPKP}" == "true" ]; then
download_shared_artifacts
download_gtk3
fi
is_flattened
if [ "${DO_HSTS}" == "true" ]; then
compare_hsts_files
if [ $? != 0 ]; then
HSTS_UPDATED=true
fi
fi
if [ "${DO_HPKP}" == "true" ]; then
compare_hpkp_files
if [ $? != 0 ]; then
HPKP_UPDATED=true
fi
fi
if [ "${DO_BLOCKLIST}" == "true" ]; then
compare_blocklist_files
if [ $? != 0 ]; then
BLOCKLIST_UPDATED=true
fi
fi
if [ "${HSTS_UPDATED}" == "false" -a "${HPKP_UPDATED}" == "false" -a "${BLOCKLIST_UPDATED}" == "false" ]; then
echo "INFO: no updates required. Exiting."
exit 0
else
if [ "${DRY_RUN}" == "true" ]; then
echo "INFO: Updates are available, not updating hg in dry-run mode."
exit 2
fi
fi
clone_repo
if [ "${HSTS_UPDATED}" == "true" ]; then
commit_hsts_files
fi
if [ "${HPKP_UPDATED}" == "true" ]; then
commit_hpkp_files
fi
if [ "${BLOCKLIST_UPDATED}" == "true" ]; then
commit_blocklist_files
fi
push_repo