diff --git a/tools/code.angularjs.org/publish.sh b/tools/code.angularjs.org/publish.sh new file mode 100755 index 0000000000..7df033f202 --- /dev/null +++ b/tools/code.angularjs.org/publish.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Script for updating code.angularjs.org repo from current local build. + +echo "#################################" +echo "## Update code.angularjs.org ###" +echo "#################################" + +ARG_DEFS=( + "--action=(prepare|publish)" + "--version-number=([0-9]+\.[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?)" +) + +function init { + TMP_DIR=$(resolveDir ../../tmp) + BUILD_DIR=$(resolveDir ../../dist/bundle) + REPO_DIR=$TMP_DIR/code.angularjs.org + # TODO: replace with version read from the bundle dir. + NEW_VERSION=$VERSION_NUMBER + if [[ "$NEW_VERSION" =~ sha ]]; then + IS_SNAPSHOT_BUILD=true + else + IS_SNAPSHOT_BUILD= + fi +} + +function prepare { + + echo "-- Cloning code.angularjs.org" + git clone git@github.com:angular/code.angularjs.org.git $REPO_DIR --depth=1 + + echo "-- Updating code.angularjs.org" + + if [[ $IS_SNAPSHOT_BUILD ]]; then + # + # update the snapshot folder + # + rm -rf $REPO_DIR/snapshot-angular2/ + mkdir $REPO_DIR/snapshot-angular2 + cp -r $BUILD_DIR/* $REPO_DIR/snapshot-angular2/ + else + # + # copy the files from the build + # + mkdir $REPO_DIR/$NEW_VERSION + cp -r $BUILD_DIR/* $REPO_DIR/$NEW_VERSION/ + fi + + # + # commit + # + echo "-- Committing code.angularjs.org" + cd $REPO_DIR + git add -A + git commit -m "v$NEW_VERSION" +} + + +function _update_code() { + cd $REPO_DIR + + echo "-- Pushing code.angularjs.org" + git push origin master + + for backend in "$@" ; do + echo "-- Refreshing code.angularjs.org: backend=$backend" + curl http://$backend:8003/gitFetchSite.php + done +} + +function publish { + # The TXT record for backends.angularjs.org is a CSV of the IP addresses for + # the currently serving Compute Engine backends. + # code.angularjs.org is served out of port 8003 on these backends. + backends=("$(dig backends.angularjs.org +short TXT | python -c 'print raw_input()[1:-1].replace(",", "\n")')") + _update_code ${backends[@]} +} + +source $(dirname $0)/../utils.inc diff --git a/tools/code.angularjs.org/unpublish.sh b/tools/code.angularjs.org/unpublish.sh new file mode 100755 index 0000000000..26652a3f9e --- /dev/null +++ b/tools/code.angularjs.org/unpublish.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Script for removing specified release dir from code.angularjs.org. + +echo "################################################" +echo "## Remove a version from code.angular.js.org ###" +echo "################################################" + +ARG_DEFS=( + "--action=(prepare|publish)" + "--version-number=([0-9]+\.[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?)" +) + +function init { + TMP_DIR=$(resolveDir ../../tmp) + REPO_DIR=$TMP_DIR/code.angularjs.org + echo "code tmp $TMP_DIR" +} + +function prepare { + echo "-- Cloning code.angularjs.org" + git clone git@github.com:angular/code.angularjs.org.git $REPO_DIR + + # + # Remove the files from the repo + # + echo "-- Removing $VERSION_NUMBER from code.angularjs.org" + cd $REPO_DIR + if [ -d "$VERSION_NUMBER" ]; then + git rm -r $VERSION_NUMBER + echo "-- Committing removal to code.angularjs.org" + git commit -m "removing v$VERSION_NUMBER" + else + echo "-- Version: $VERSION_NUMBER does not exist in code.angularjs.org!" + fi +} + +function publish { + cd $REPO_DIR + + echo "-- Pushing code.angularjs.org to github" + git push origin master +} + +source $(dirname $0)/../utils.inc diff --git a/tools/utils.inc b/tools/utils.inc new file mode 100644 index 0000000000..919f7df979 --- /dev/null +++ b/tools/utils.inc @@ -0,0 +1,279 @@ +# This file provides: +# - a default control flow +# * initializes the environment +# * able to mock "git push" in your script and in all sub scripts +# * call a function in your script based on the arguments +# - named argument parsing and automatic generation of the "usage" for your script +# - intercepting "git push" in your script and all sub scripts +# - utility functions +# +# Usage: +# - define the variable ARGS_DEF (see below) with the arguments for your script +# - include this file using `source utils.inc` at the end of your script. +# +# Default control flow: +# 0. Set the current directory to the directory of the script. By this +# the script can be called from anywhere. +# 1. Parse the named arguments +# 2. If the parameter "git_push_dryrun" is set, all calls to `git push` in this script +# or in child scripts will be intercepted so that the `--dry-run` and `--porcelain` is added +# to show what the push would do but not actually do it. +# 3. If the parameter "verbose" is set, the `-x` flag will be set in bash. +# 4. The function "init" will be called if it exists +# 5. If the parameter "action" is set, it will call the function with the name of that parameter. +# Otherwise the function "run" will be called. +# +# Named Argument Parsing: +# - The variable ARGS_DEF defines the valid command arguments +# * Required args syntax: --paramName=paramRegex +# * Optional args syntax: [--paramName=paramRegex] +# * e.g. ARG_DEFS=("--required_param=(.+)" "[--optional_param=(.+)]") +# - Checks that: +# * all arguments match to an entry in ARGS_DEF +# * all required arguments are present +# * all arguments match their regex +# - Afterwards, every parameter value will be stored in a variable +# with the name of the parameter in upper case (with dash converted to underscore). +# +# Special arguments that are always available: +# - "--action=.*": This parameter will be used to execute a function with that name when the +# script is started +# - "--git_push_dryrun=true": This will intercept all calls to `git push` in this script +# or in child scripts so that the `--dry-run` and `--porcelain` is added +# to show what the push would do but not actually do it. +# - "--verbose=true": This will set the `-x` flag in bash so that all calls will be logged +# +# Utility functions: +# - readJsonProp +# - replaceJsonProp +# - resolveDir +# - getVar +# - serVar +# - isFunction + +# always stop on errors +set -e + +function usage { + echo "Usage: ${0} ${ARG_DEFS[@]}" + exit 1 +} + + +function parseArgs { + local REQUIRED_ARG_NAMES=() + + # -- helper functions + function varName { + # everything to upper case and dash to underscore + echo ${1//-/_} | tr '[:lower:]' '[:upper:]' + } + + function readArgDefs { + local ARG_DEF + local AD_OPTIONAL + local AD_NAME + local AD_RE + + # -- helper functions + function parseArgDef { + local ARG_DEF_REGEX="(\[?)--([^=]+)=(.*)" + if [[ ! $1 =~ $ARG_DEF_REGEX ]]; then + echo "Internal error: arg def has wrong format: $ARG_DEF" + exit 1 + fi + AD_OPTIONAL="${BASH_REMATCH[1]}" + AD_NAME="${BASH_REMATCH[2]}" + AD_RE="${BASH_REMATCH[3]}" + if [[ $AD_OPTIONAL ]]; then + # Remove last bracket for optional args. + # Can't put this into the ARG_DEF_REGEX somehow... + AD_RE=${AD_RE%?} + fi + } + + # -- run + for ARG_DEF in "${ARG_DEFS[@]}" + do + parseArgDef $ARG_DEF + + local AD_NAME_UPPER=$(varName $AD_NAME) + setVar "${AD_NAME_UPPER}_OPTIONAL" "$AD_OPTIONAL" + setVar "${AD_NAME_UPPER}_RE" "$AD_RE" + if [[ ! $AD_OPTIONAL ]]; then + REQUIRED_ARG_NAMES+=($AD_NAME) + fi + done + } + + function readAndValidateArgs { + local ARG_NAME + local ARG_VALUE + local ARG_NAME_UPPER + + # -- helper functions + function parseArg { + local ARG_REGEX="--([^=]+)=?(.*)" + + if [[ ! $1 =~ $ARG_REGEX ]]; then + echo "Can't parse argument $i" + usage + fi + + ARG_NAME="${BASH_REMATCH[1]}" + ARG_VALUE="${BASH_REMATCH[2]}" + ARG_NAME_UPPER=$(varName $ARG_NAME) + } + + function validateArg { + local AD_RE=$(getVar ${ARG_NAME_UPPER}_RE) + + if [[ ! $AD_RE ]]; then + echo "Unknown option: $ARG_NAME" + usage + fi + + if [[ ! $ARG_VALUE =~ ^${AD_RE}$ ]]; then + echo "Wrong format: $ARG_NAME" + usage; + fi + + # validate that the "action" option points to a valid function + if [[ $ARG_NAME == "action" ]] && ! isFunction $ARG_VALUE; then + echo "No action $ARG_VALUE defined in this script" + usage; + fi + } + + # -- run + for i in "$@" + do + parseArg $i + validateArg + setVar "${ARG_NAME_UPPER}" "$ARG_VALUE" + done + } + + function checkMissingArgs { + local ARG_NAME + for ARG_NAME in "${REQUIRED_ARG_NAMES[@]}" + do + ARG_VALUE=$(getVar $(varName $ARG_NAME)) + + if [[ ! $ARG_VALUE ]]; then + echo "Missing: $ARG_NAME" + usage; + fi + done + } + + # -- run + readArgDefs + readAndValidateArgs "$@" + checkMissingArgs + +} + +# getVar(varName) +function getVar { + echo ${!1} +} + +# setVar(varName, varValue) +function setVar { + eval "$1=\"$2\"" +} + +# isFunction(name) +# - to be used in an if, so return 0 if successful and 1 if not! +function isFunction { + if [[ $(type -t $1) == "function" ]]; then + return 0 + else + return 1 + fi +} + +# readJsonProp(jsonFile, property) +# - restriction: property needs to be on a single line! +function readJsonProp { + echo $(sed -En 's/.*"'$2'"[ ]*:[ ]*"(.*)".*/\1/p' $1) +} + +# replaceJsonProp(jsonFile, propertyRegex, valueRegex, replacePattern) +# - note: propertyRegex will be automatically placed into a +# capturing group! -> all other groups start at index 2! +function replaceJsonProp { + replaceInFile $1 '"('$2')"[ ]*:[ ]*"'$3'"' '"\1": "'$4'"' +} + +# replaceInFile(file, findPattern, replacePattern) +function replaceInFile { + sed -i .tmp -E "s/$2/$3/" $1 + rm $1.tmp +} + +# resolveDir(relativeDir) +# - resolves a directory relative to the current script +function resolveDir { + echo $(cd $SCRIPT_DIR; cd $1; pwd) +} + +function git_push_dryrun_proxy { + echo "## git push dryrun proxy enabled!" + export ORIGIN_GIT=$(which git) + + function git { + local ARGS=("$@") + local RC + if [[ $1 == "push" ]]; then + ARGS+=("--dry-run" "--porcelain") + echo "####### START GIT PUSH DRYRUN #######" + echo "${ARGS[@]}" + fi + if [[ $1 == "commit" ]]; then + echo "${ARGS[@]}" + fi + $ORIGIN_GIT "${ARGS[@]}" + RC=$? + if [[ $1 == "push" ]]; then + echo "####### END GIT PUSH DRYRUN #######" + fi + return $RC + } + + export -f git +} + +function main { + # normalize the working dir to the directory of the script + cd $(dirname $0);SCRIPT_DIR=$(pwd) + + ARG_DEFS+=("[--git-push-dryrun=(true|false)]" "[--verbose=(true|false)]") + parseArgs "$@" + + # --git_push_dryrun argument + if [[ $GIT_PUSH_DRYRUN == "true" ]]; then + git_push_dryrun_proxy + fi + + # --verbose argument + if [[ $VERBOSE == "true" ]]; then + set -x + fi + + if isFunction init; then + init "$@" + fi + + # jump to the function denoted by the --action argument, + # otherwise call the "run" function + if [[ $ACTION ]]; then + $ACTION "$@" + else + run "$@" + fi +} + + +main "$@"