diff --git a/Gopkg.lock b/Gopkg.lock index bea0155..3a7d1d2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,11 +3,11 @@ [[projects]] branch = "master" - digest = "1:0cabae2c3a124c49ed5e862866e1228f08a1a6e49d0daf971e5a72e5e56095a4" + digest = "1:7f69cbcecc19b16348db79ac39f010e12fbfc86f3cf4b2712aacc460e882ebfa" name = "github.com/knative/test-infra" packages = ["scripts"] pruneopts = "UT" - revision = "2377fbc40f81501f2bc09a4e1e359a7ec7c3528e" + revision = "89e4aae358be056ee70b595c20106a4a5c70fdc1" [solve-meta] analyzer-name = "dep" diff --git a/test/presubmit-tests.sh b/test/presubmit-tests.sh index c29ca91..324fd6e 100755 --- a/test/presubmit-tests.sh +++ b/test/presubmit-tests.sh @@ -20,16 +20,12 @@ source $(dirname $0)/../vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh -function build_tests() { - header "TODO(#23): write build tests" -} +# TODO(#23): Write more build tests. function unit_tests() { header "TODO(#22): Write unit tests" } -function integration_tests() { - ./test/e2e-tests.sh -} +# We use the default build and integration test runners. main $@ diff --git a/vendor/github.com/knative/test-infra/scripts/README.md b/vendor/github.com/knative/test-infra/scripts/README.md index 0e7ab57..dcf7dc9 100644 --- a/vendor/github.com/knative/test-infra/scripts/README.md +++ b/vendor/github.com/knative/test-infra/scripts/README.md @@ -9,21 +9,35 @@ This is a helper script to run the presubmit tests. To use it: 1. Source this script. -1. Define the functions `build_tests()` and `unit_tests()`. They should run all -tests (i.e., not fail fast), and return 0 if all passed, 1 if a failure -occurred. The environment variables `RUN_BUILD_TESTS`, `RUN_UNIT_TESTS` and -`RUN_INTEGRATION_TESTS` are set to 0 (false) or 1 (true) accordingly. If -`--emit-metrics` is passed, `EMIT_METRICS` will be set to 1. - -1. [optional] Define the function `integration_tests()`, just like the previous -ones. If you don't define this function, the default action for running the -integration tests is to call the `./test/e2e-tests.sh` script (passing the -`--emit-metrics` flag if necessary). - -1. [optional] Define the functions `pre_integration_tests()` or -`post_integration_tests()`. These functions will be called before or after the -integration tests (either your custom one or the default action) and will cause -the test to fail if they don't return success. +1. [optional] Define the function `build_tests()`. If you don't define this + function, the default action for running the build tests is to: + - lint and link check markdown files + - run `go build` on the entire repo + - run `/hack/verify-codegen.sh` (if it exists) + - check licenses in `/cmd` (if it exists) + +1. [optional] Define the functions `pre_build_tests()` and/or + `post_build_tests()`. These functions will be called before or after the + build tests (either your custom one or the default action) and will cause + the test to fail if they don't return success. + +1. [optional] Define the function `unit_tests()`. If you don't define this + function, the default action for running the unit tests is to run all go tests + in the repo. + +1. [optional] Define the functions `pre_unit_tests()` and/or + `post_unit_tests()`. These functions will be called before or after the + unit tests (either your custom one or the default action) and will cause + the test to fail if they don't return success. + +1. [optional] Define the function `integration_tests()`. If you don't define + this function, the default action for running the integration tests is to run + all run all `./test/e2e-*tests.sh` scripts, in sequence. + +1. [optional] Define the functions `pre_integration_tests()` and/or + `post_integration_tests()`. These functions will be called before or after the + integration tests (either your custom one or the default action) and will cause + the test to fail if they don't return success. 1. Call the `main()` function passing `$@` (without quotes). @@ -33,20 +47,27 @@ integration tests). Use the flags `--build-tests`, `--unit-tests` and `--integration-tests` to run a specific set of tests. The flag `--emit-metrics` is used to emit metrics when -running the tests, and is automatically handled by the default action (see -above). +running the tests, and is automatically handled by the default action for +integration tests (see above). + +The script will automatically skip all presubmit tests for PRs where all changed +files are exempt of tests (e.g., a PR changing only the `OWNERS` file). + +Also, for PRs touching only markdown files, the unit and integration tests are +skipped. ### Sample presubmit test script ```bash source vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh -function build_tests() { - go build . +function post_build_tests() { + echo "Cleaning up after build tests" + rm -fr ./build-cache } function unit_tests() { - report_go_test . + make -C tests test } function pre_integration_tests() { @@ -66,43 +87,44 @@ This is a helper script for Knative E2E test scripts. To use it: 1. Source the script. 1. [optional] Write the `teardown()` function, which will tear down your test -resources. + resources. 1. [optional] Write the `dump_extra_cluster_state()` function. It will be -called when a test fails, and can dump extra information about the current state -of the cluster (tipically using `kubectl`). + called when a test fails, and can dump extra information about the current state + of the cluster (tipically using `kubectl`). 1. [optional] Write the `parse_flags()` function. It will be called whenever an -unrecognized flag is passed to the script, allowing you to define your own flags. -The function must return 0 if the flag is unrecognized, or the number of items -to skip in the command line if the flag was parsed successfully. For example, -return 1 for a simple flag, and 2 for a flag with a parameter. + unrecognized flag is passed to the script, allowing you to define your own flags. + The function must return 0 if the flag is unrecognized, or the number of items + to skip in the command line if the flag was parsed successfully. For example, + return 1 for a simple flag, and 2 for a flag with a parameter. 1. Call the `initialize()` function passing `$@` (without quotes). 1. Write logic for the end-to-end tests. Run all go tests using `go_test_e2e()` -(or `report_go_test()` if you need a more fine-grained control) and call -`fail_test()` or `success()` if any of them failed. The environment variables -`DOCKER_REPO_OVERRIDE`, `K8S_CLUSTER_OVERRIDE` and `K8S_USER_OVERRIDE` will be set -according to the test cluster. You can also use the following boolean (0 is false, -1 is true) environment variables for the logic: - * `EMIT_METRICS`: true if `--emit-metrics` was passed. - * `USING_EXISTING_CLUSTER`: true if the test cluster is an already existing one, -and not a temporary cluster created by `kubetest`. + (or `report_go_test()` if you need a more fine-grained control) and call + `fail_test()` or `success()` if any of them failed. The environment variables + `DOCKER_REPO_OVERRIDE`, `K8S_CLUSTER_OVERRIDE` and `K8S_USER_OVERRIDE` will be + set according to the test cluster. You can also use the following boolean (0 is + false, 1 is true) environment variables for the logic: + + - `EMIT_METRICS`: true if `--emit-metrics` was passed. + - `USING_EXISTING_CLUSTER`: true if the test cluster is an already existing one, + and not a temporary cluster created by `kubetest`. - All environment variables above are marked read-only. + All environment variables above are marked read-only. **Notes:** 1. Calling your script without arguments will create a new cluster in the GCP -project `$PROJECT_ID` and run the tests against it. + project `$PROJECT_ID` and run the tests against it. 1. Calling your script with `--run-tests` and the variables `K8S_CLUSTER_OVERRIDE`, -`K8S_USER_OVERRIDE` and `DOCKER_REPO_OVERRIDE` set will immediately start the -tests against the cluster. + `K8S_USER_OVERRIDE` and `DOCKER_REPO_OVERRIDE` set will immediately start the + tests against the cluster. 1. You can force running the tests against a specific GKE cluster version by using -the `--cluster-version` flag and passing a X.Y.Z version as the flag value. + the `--cluster-version` flag and passing a X.Y.Z version as the flag value. ### Sample end-to-end test script @@ -150,31 +172,38 @@ This is a helper script for Knative release scripts. To use it: 1. Call the `initialize()` function passing `$@` (without quotes). 1. Call the `run_validation_tests()` function passing the script or executable that -runs the release validation tests. It will call the script to run the tests unless -`--skip_tests` was passed. + runs the release validation tests. It will call the script to run the tests unless + `--skip_tests` was passed. 1. Write logic for the release process. Call `publish_yaml()` to publish the manifest(s), -`tag_releases_in_yaml()` to tag the generated images, `branch_release()` to branch -named releases. Use the following boolean (0 is false, 1 is true) and string environment -variables for the logic: - * `RELEASE_VERSION`: contains the release version if `--version` was passed. This -also overrides the value of the `TAG` variable as `v`. - * `RELEASE_BRANCH`: contains the release branch if `--branch` was passed. Otherwise -it's empty and `master` HEAD will be considered the release branch. - * `RELEASE_NOTES`: contains the filename with the release notes if `--release-notes` -was passed. The release notes is a simple markdown file. - * `SKIP_TESTS`: true if `--skip-tests` was passed. This is handled automatically -by the run_validation_tests() function. - * `TAG_RELEASE`: true if `--tag-release` was passed. In this case, the environment -variable `TAG` will contain the release tag in the form `vYYYYMMDD-`. - * `PUBLISH_RELEASE`: true if `--publish` was passed. In this case, the environment -variable `KO_FLAGS` will be updated with the `-L` option. - * `BRANCH_RELEASE`: true if both `--version` and `--publish-release` were passed. - - All boolean environment variables default to false for safety. - - All environment variables above, except `KO_FLAGS`, are marked read-only once -`initialize()` is called. + `tag_releases_in_yaml()` to tag the generated images, `branch_release()` to branch + named releases. Use the following boolean (0 is false, 1 is true) and string environment + variables for the logic: + + - `RELEASE_VERSION`: contains the release version if `--version` was passed. This + also overrides the value of the `TAG` variable as `v`. + - `RELEASE_BRANCH`: contains the release branch if `--branch` was passed. Otherwise + it's empty and `master` HEAD will be considered the release branch. + - `RELEASE_NOTES`: contains the filename with the release notes if `--release-notes` + was passed. The release notes is a simple markdown file. + - `RELEASE_GCS_BUCKET`: contains the GCS bucket name to store the manifests if + `--release-gcs` was passed, otherwise the default value `knative-nightly/` + will be used. It is empty if `--publish` was not passed. + - `KO_DOCKER_REPO`: contains the GCR to store the images if `--release-gcr` was + passed, otherwise the default value `gcr.io/knative-nightly` will be used. It + is set to `ko.local` if `--publish` was not passed. + - `SKIP_TESTS`: true if `--skip-tests` was passed. This is handled automatically + by the `run_validation_tests()` function. + - `TAG_RELEASE`: true if `--tag-release` was passed. In this case, the environment + variable `TAG` will contain the release tag in the form `vYYYYMMDD-`. + - `PUBLISH_RELEASE`: true if `--publish` was passed. In this case, the environment + variable `KO_FLAGS` will be updated with the `-L` option. + - `BRANCH_RELEASE`: true if both `--version` and `--publish-release` were passed. + + All boolean environment variables default to false for safety. + + All environment variables above, except `KO_FLAGS`, are marked read-only once + `initialize()` is called. ### Sample release script @@ -186,14 +215,12 @@ initialize $@ run_validation_tests ./test/presubmit-tests.sh # config/ contains the manifests -KO_DOCKER_REPO=gcr.io/knative-foo ko resolve ${KO_FLAGS} -f config/ > release.yaml -tag_images_in_yaml release.yaml $KO_DOCKER_REPO $TAG +tag_images_in_yaml release.yaml if (( PUBLISH_RELEASE )); then - # gs://knative-foo hosts the manifest - publish_yaml release.yaml knative-foo $TAG + publish_yaml release.yaml fi branch_release "Knative Foo" release.yaml diff --git a/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh b/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh index b1dd664..49562ad 100755 --- a/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh +++ b/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh @@ -36,14 +36,17 @@ function build_resource_name() { } # Test cluster parameters -readonly E2E_BASE_NAME=k$(basename ${REPO_ROOT_DIR}) +readonly E2E_BASE_NAME="k${REPO_NAME}" readonly E2E_CLUSTER_NAME=$(build_resource_name e2e-cls) readonly E2E_NETWORK_NAME=$(build_resource_name e2e-net) readonly E2E_CLUSTER_REGION=us-central1 -readonly E2E_CLUSTER_ZONE=${E2E_CLUSTER_REGION}-a -readonly E2E_CLUSTER_NODES=3 readonly E2E_CLUSTER_MACHINE=n1-standard-4 readonly TEST_RESULT_FILE=/tmp/${E2E_BASE_NAME}-e2e-result +# Each knative repository may have a different cluster size requirement here, +# so we allow calling code to set these parameters. If they are not set we +# use some sane defaults. +readonly E2E_MIN_CLUSTER_NODES=${E2E_MIN_CLUSTER_NODES:-1} +readonly E2E_MAX_CLUSTER_NODES=${E2E_MAX_CLUSTER_NODES:-3} # Flag whether test is using a boskos GCP project IS_BOSKOS=0 @@ -60,14 +63,6 @@ function teardown_test_resources() { rm -fr kubernetes kubernetes.tar.gz } -# Exit test, dumping current state info. -# Parameters: $1 - error message (optional). -function fail_test() { - [[ -n $1 ]] && echo "ERROR: $1" - dump_cluster_state - exit 1 -} - # Run the given E2E tests. Assume tests are tagged e2e, unless `-tags=XXX` is passed. # Parameters: $1..$n - any go test flags, then directories containing the tests to run. function go_test_e2e() { @@ -149,20 +144,21 @@ function create_test_cluster() { set -o pipefail header "Creating test cluster" + + echo "Cluster will have a minimum of ${E2E_MIN_CLUSTER_NODES} and a maximum of ${E2E_MAX_CLUSTER_NODES} nodes." + # Smallest cluster required to run the end-to-end-tests local CLUSTER_CREATION_ARGS=( - --gke-create-args="--enable-autoscaling --min-nodes=1 --max-nodes=${E2E_CLUSTER_NODES} --scopes=cloud-platform --enable-basic-auth --no-issue-client-certificate" - --gke-shape={\"default\":{\"Nodes\":${E2E_CLUSTER_NODES}\,\"MachineType\":\"${E2E_CLUSTER_MACHINE}\"}} + --gke-create-args="--enable-autoscaling --min-nodes=${E2E_MIN_CLUSTER_NODES} --max-nodes=${E2E_MAX_CLUSTER_NODES} --scopes=cloud-platform --enable-basic-auth --no-issue-client-certificate" + --gke-shape={\"default\":{\"Nodes\":${E2E_MIN_CLUSTER_NODES}\,\"MachineType\":\"${E2E_CLUSTER_MACHINE}\"}} --provider=gke --deployment=gke --cluster="${E2E_CLUSTER_NAME}" - --gcp-zone="${E2E_CLUSTER_ZONE}" + --gcp-region="${E2E_CLUSTER_REGION}" --gcp-network="${E2E_NETWORK_NAME}" --gke-environment=prod ) - if (( IS_BOSKOS )); then - CLUSTER_CREATION_ARGS+=(--gcp-service-account=/etc/service-account/service-account.json) - else + if (( ! IS_BOSKOS )); then CLUSTER_CREATION_ARGS+=(--gcp-project=${GCP_PROJECT}) fi # SSH keys are not used, but kubetest checks for their existence. @@ -175,8 +171,8 @@ function create_test_cluster() { # be a writeable docker repo. export K8S_USER_OVERRIDE= export K8S_CLUSTER_OVERRIDE= - # Assume test failed (see more details at the end of this script). - echo -n "1"> ${TEST_RESULT_FILE} + # Assume test failed (see details in set_test_return_code()). + set_test_return_code 1 local test_cmd_args="--run-tests" (( EMIT_METRICS )) && test_cmd_args+=" --emit-metrics" [[ -n "${GCP_PROJECT}" ]] && test_cmd_args+=" --gcp-project ${GCP_PROJECT}" @@ -241,7 +237,7 @@ function setup_test_cluster() { if [[ -z ${K8S_CLUSTER_OVERRIDE} ]]; then USING_EXISTING_CLUSTER=0 export K8S_CLUSTER_OVERRIDE=$(kubectl config current-context) - acquire_cluster_admin_role ${K8S_USER_OVERRIDE} ${E2E_CLUSTER_NAME} ${E2E_CLUSTER_ZONE} + acquire_cluster_admin_role ${K8S_USER_OVERRIDE} ${E2E_CLUSTER_NAME} ${E2E_CLUSTER_REGION} # Make sure we're in the default namespace. Currently kubetest switches to # test-pods namespace when creating the cluster. kubectl config set-context $K8S_CLUSTER_OVERRIDE --namespace=default @@ -257,6 +253,7 @@ function setup_test_cluster() { echo "- Docker is ${DOCKER_REPO_OVERRIDE}" export KO_DOCKER_REPO="${DOCKER_REPO_OVERRIDE}" + export KO_DATA_PATH="${REPO_ROOT_DIR}/.git" trap teardown_test_resources EXIT @@ -274,19 +271,34 @@ function setup_test_cluster() { set +o pipefail } -function success() { +# Set the return code that the test script will return. +# Parameters: $1 - return code (0-255) +function set_test_return_code() { # kubetest teardown might fail and thus incorrectly report failure of the # script, even if the tests pass. # We store the real test result to return it later, ignoring any teardown # failure in kubetest. # TODO(adrcunha): Get rid of this workaround. - echo -n "0"> ${TEST_RESULT_FILE} + echo -n "$1"> ${TEST_RESULT_FILE} +} + +function success() { + set_test_return_code 0 echo "**************************************" echo "*** E2E TESTS PASSED ***" echo "**************************************" exit 0 } +# Exit test, dumping current state info. +# Parameters: $1 - error message (optional). +function fail_test() { + set_test_return_code 1 + [[ -n $1 ]] && echo "ERROR: $1" + dump_cluster_state + exit 1 +} + RUN_TESTS=0 EMIT_METRICS=0 USING_EXISTING_CLUSTER=1 @@ -294,11 +306,6 @@ GCP_PROJECT="" E2E_SCRIPT="" E2E_CLUSTER_VERSION="" -function abort() { - echo "error: $@" - exit 1 -} - # Parse flags and initialize the test cluster. function initialize() { # Normalize calling script path; we can't use readlink because it's not available everywhere @@ -357,10 +364,8 @@ function initialize() { (( IS_PROW )) && [[ -z "${GCP_PROJECT}" ]] && IS_BOSKOS=1 # Safety checks - - if [[ "${DOCKER_REPO_OVERRIDE}" =~ ^gcr.io/knative-(releases|nightly)/?$ ]]; then - abort "\$DOCKER_REPO_OVERRIDE is set to ${DOCKER_REPO_OVERRIDE}, which is forbidden" - fi + is_protected_gcr ${DOCKER_REPO_OVERRIDE} && \ + abort "\$DOCKER_REPO_OVERRIDE set to ${DOCKER_REPO_OVERRIDE}, which is forbidden" readonly RUN_TESTS readonly EMIT_METRICS diff --git a/vendor/github.com/knative/test-infra/scripts/library.sh b/vendor/github.com/knative/test-infra/scripts/library.sh index ba267d9..9b7a78f 100755 --- a/vendor/github.com/knative/test-infra/scripts/library.sh +++ b/vendor/github.com/knative/test-infra/scripts/library.sh @@ -23,11 +23,12 @@ readonly SERVING_GKE_VERSION=latest readonly SERVING_GKE_IMAGE=cos # Public latest stable nightly images and yaml files. -readonly KNATIVE_ISTIO_CRD_YAML=https://storage.googleapis.com/knative-nightly/serving/latest/istio-crds.yaml -readonly KNATIVE_ISTIO_YAML=https://storage.googleapis.com/knative-nightly/serving/latest/istio.yaml -readonly KNATIVE_SERVING_RELEASE=https://storage.googleapis.com/knative-nightly/serving/latest/release.yaml -readonly KNATIVE_BUILD_RELEASE=https://storage.googleapis.com/knative-nightly/build/latest/release.yaml -readonly KNATIVE_EVENTING_RELEASE=https://storage.googleapis.com/knative-nightly/eventing/latest/release.yaml +readonly KNATIVE_BASE_YAML_SOURCE=https://storage.googleapis.com/knative-nightly/@/latest +readonly KNATIVE_ISTIO_CRD_YAML=${KNATIVE_BASE_YAML_SOURCE/@/serving}/istio-crds.yaml +readonly KNATIVE_ISTIO_YAML=${KNATIVE_BASE_YAML_SOURCE/@/serving}/istio.yaml +readonly KNATIVE_SERVING_RELEASE=${KNATIVE_BASE_YAML_SOURCE/@/serving}/serving.yaml +readonly KNATIVE_BUILD_RELEASE=${KNATIVE_BASE_YAML_SOURCE/@/build}/release.yaml +readonly KNATIVE_EVENTING_RELEASE=${KNATIVE_BASE_YAML_SOURCE/@/eventing}/release.yaml # Conveniently set GOPATH if unset if [[ -z "${GOPATH:-}" ]]; then @@ -41,13 +42,24 @@ fi [[ -n "${PROW_JOB_ID:-}" ]] && IS_PROW=1 || IS_PROW=0 readonly IS_PROW readonly REPO_ROOT_DIR="$(git rev-parse --show-toplevel)" +readonly REPO_NAME="$(basename ${REPO_ROOT_DIR})" + +# On a Prow job, redirect stderr to stdout so it's synchronously added to log +(( IS_PROW )) && exec 2>&1 + +# Print error message and exit 1 +# Parameters: $1..$n - error message to be displayed +function abort() { + echo "error: $@" + exit 1 +} # Display a box banner. # Parameters: $1 - character to use for the box. # $2 - banner message. function make_banner() { local msg="$1$1$1$1 $2 $1$1$1$1" - local border="${msg//[-0-9A-Za-z _.,\/]/$1}" + local border="${msg//[-0-9A-Za-z _.,\/()]/$1}" echo -e "${border}\n${msg}\n${border}" } @@ -72,20 +84,6 @@ function function_exists() { [[ "$(type -t $1)" == "function" ]] } -# Remove ALL images in the given GCR repository. -# Parameters: $1 - GCR repository. -function delete_gcr_images() { - for image in $(gcloud --format='value(name)' container images list --repository=$1); do - echo "Checking ${image} for removal" - delete_gcr_images ${image} - for digest in $(gcloud --format='get(digest)' container images list-tags ${image} --limit=99999); do - local full_image="${image}@${digest}" - echo "Removing ${full_image}" - gcloud container images delete -q --force-delete-tags ${full_image} - done - done -} - # Waits until the given object doesn't exist. # Parameters: $1 - the kind of the object. # $2 - object's name. @@ -100,8 +98,8 @@ function wait_until_object_does_not_exist() { fi echo -n "Waiting until ${DESCRIPTION} does not exist" for i in {1..150}; do # timeout after 5 minutes - if kubectl ${KUBECTL_ARGS} > /dev/null 2>&1; then - echo "\n${DESCRIPTION} does not exist" + if ! kubectl ${KUBECTL_ARGS} > /dev/null 2>&1; then + echo -e "\n${DESCRIPTION} does not exist" return 0 fi echo -n "." @@ -140,7 +138,6 @@ function wait_until_pods_running() { sleep 2 done echo -e "\n\nERROR: timeout waiting for pods to come up\n${pods}" - kubectl get pods -n $1 return 1 } @@ -201,12 +198,12 @@ function get_app_pods() { # Sets the given user as cluster admin. # Parameters: $1 - user # $2 - cluster name -# $3 - cluster zone +# $3 - cluster region function acquire_cluster_admin_role() { # Get the password of the admin and use it, as the service account (or the user) # might not have the necessary permission. local password=$(gcloud --format="value(masterAuth.password)" \ - container clusters describe $2 --zone=$3) + container clusters describe $2 --region=$3) if [[ -n "${password}" ]]; then # Cluster created with basic authentication kubectl config set-credentials cluster-admin \ @@ -216,9 +213,9 @@ function acquire_cluster_admin_role() { local key=$(mktemp) echo "Certificate in ${cert}, key in ${key}" gcloud --format="value(masterAuth.clientCertificate)" \ - container clusters describe $2 --zone=$3 | base64 -d > ${cert} + container clusters describe $2 --region=$3 | base64 -d > ${cert} gcloud --format="value(masterAuth.clientKey)" \ - container clusters describe $2 --zone=$3 | base64 -d > ${key} + container clusters describe $2 --region=$3 | base64 -d > ${key} kubectl config set-credentials cluster-admin \ --client-certificate=${cert} --client-key=${key} fi @@ -229,10 +226,10 @@ function acquire_cluster_admin_role() { --user=$1 # Reset back to the default account gcloud container clusters get-credentials \ - $2 --zone=$3 --project $(gcloud config get-value project) + $2 --region=$3 --project $(gcloud config get-value project) } -# Runs a go test and generate a junit summary through bazel. +# Runs a go test and generate a junit summary. # Parameters: $1... - parameters to go test function report_go_test() { # Run tests in verbose mode to capture details. @@ -246,102 +243,18 @@ function report_go_test() { fi echo "Running tests with '${go_test}'" local report=$(mktemp) - local failed=0 - local test_count=0 - local tests_failed=0 - ${go_test} > ${report} || failed=$? + ${go_test} | tee ${report} + local failed=( ${PIPESTATUS[@]} ) + [[ ${failed[0]} -eq 0 ]] && failed=${failed[1]} || failed=${failed[0]} echo "Finished run, return code is ${failed}" - # Tests didn't run. - [[ ! -s ${report} ]] && return 1 - # Create WORKSPACE file, required to use bazel, if necessary. - touch WORKSPACE - local targets="" - local last_run="" - local test_files="" - # Parse the report and generate fake tests for each passing/failing test. - echo "Start parsing results, summary:" - while read line ; do - local fields=(`echo -n ${line}`) - local field0="${fields[0]}" - local field1="${fields[1]}" - local name="${fields[2]}" - # Deal with a SIGQUIT log entry (usually a test timeout). - # This is a fallback in case there's no kill signal log entry. - # SIGQUIT: quit - if [[ "${field0}" == "SIGQUIT:" ]]; then - name="${last_run}" - field1="FAIL:" - error="${fields[@]}" - fi - # Ignore subtests (those containing slashes) - if [[ -n "${name##*/*}" ]]; then - local error="" - # Deal with a kill signal log entry (usually a test timeout). - # *** Test killed with quit: ran too long (10m0s). - if [[ "${field0}" == "***" ]]; then - name="${last_run}" - field1="FAIL:" - error="${fields[@]:1}" - fi - # Deal with a fatal log entry, which has a different format: - # fatal TestFoo foo_test.go:275 Expected "foo" but got "bar" - if [[ "${field0}" == "fatal" ]]; then - name="${field1}" - field1="FAIL:" - error="${fields[@]:3}" - fi - # Keep track of the test currently running. - if [[ "${field1}" == "RUN" ]]; then - last_run="${name}" - fi - # Handle regular go test pass/fail entry for a test. - if [[ "${field1}" == "PASS:" || "${field1}" == "FAIL:" ]]; then - echo "- ${name} :${field1}" - test_count=$(( test_count + 1 )) - local src="${name}.sh" - echo "exit 0" > ${src} - if [[ "${field1}" == "FAIL:" ]]; then - tests_failed=$(( tests_failed + 1 )) - [[ -z "${error}" ]] && read error - echo "cat < ${src} - echo "${error}" >> ${src} - echo "ERROR-EOF" >> ${src} - echo "exit 1" >> ${src} - fi - chmod +x ${src} - test_files="${test_files} ${src}" - # Populate BUILD.bazel - echo "sh_test(name=\"${name}\", srcs=[\"${src}\"])" >> BUILD.bazel - elif [[ "${field0}" == "FAIL" || "${field0}" == "ok" ]] && [[ -n "${field1}" ]]; then - echo "- ${field0} ${field1}" - # Create the package structure, move tests and BUILD file - local package=${field1/github.com\//} - local bazel_files="$(ls -1 ${test_files} BUILD.bazel 2> /dev/null)" - if [[ -n "${bazel_files}" ]]; then - mkdir -p ${package} - targets="${targets} //${package}/..." - mv ${bazel_files} ${package} - else - echo "*** INTERNAL ERROR: missing tests for ${package}, got [${bazel_files/$'\n'/, }]" - fi - test_files="" - fi - fi - done < ${report} - echo "Done parsing ${test_count} tests, ${tests_failed} tests failed" - # If any test failed, show the detailed report. - # Otherwise, we already shown the summary. - # Exception: when emitting metrics, dump the full report. - if (( failed )) || [[ "$@" == *" -emitmetrics"* ]]; then - if (( failed )); then - echo "There were ${tests_failed} test failures, full log:" - else - echo "Dumping full log as metrics were requested:" - fi - cat ${report} - fi - # Always generate the junit summary. - bazel test ${targets} > /dev/null 2>&1 || true + # Install go-junit-report if necessary. + run_go_tool github.com/jstemmer/go-junit-report go-junit-report --help > /dev/null 2>&1 + local xml=$(mktemp ${ARTIFACTS}/junit_XXXXXXXX.xml) + cat ${report} \ + | go-junit-report \ + | sed -e "s#\"github.com/knative/${REPO_NAME}/#\"#g" \ + > ${xml} + echo "XML report written to ${xml}" return ${failed} } @@ -349,11 +262,16 @@ function report_go_test() { function start_latest_knative_serving() { header "Starting Knative Serving" subheader "Installing Istio" + echo "Installing Istio CRD from ${KNATIVE_ISTIO_CRD_YAML}" kubectl apply -f ${KNATIVE_ISTIO_CRD_YAML} || return 1 + echo "Installing Istio from ${KNATIVE_ISTIO_YAML}" kubectl apply -f ${KNATIVE_ISTIO_YAML} || return 1 wait_until_pods_running istio-system || return 1 kubectl label namespace default istio-injection=enabled || return 1 + subheader "Installing Knative Build" + kubectl apply -f ${KNATIVE_BUILD_RELEASE} || return 1 subheader "Installing Knative Serving" + echo "Installing Serving from ${KNATIVE_SERVING_RELEASE}" kubectl apply -f ${KNATIVE_SERVING_RELEASE} || return 1 wait_until_pods_running knative-serving || return 1 wait_until_pods_running knative-build || return 1 @@ -432,8 +350,22 @@ function check_links_in_markdown() { } # Check format of the given markdown files. -# Parameters: $1...$n - files to inspect +# Parameters: $1..$n - files to inspect function lint_markdown() { # https://github.com/markdownlint/markdownlint run_lint_tool mdl "linting markdown files" "-r ~MD013" $@ } + +# Return 0 if the given parameter is an integer, otherwise 1 +# Parameters: $1 - an integer +function is_int() { + [[ -n $1 && $1 =~ ^[0-9]+$ ]] +} + +# Return 0 if the given parameter is the knative release/nightly gcr, 1 +# otherwise +# Parameters: $1 - gcr name, e.g. gcr.io/knative-nightly +function is_protected_gcr() { + [[ -n $1 && "$1" =~ "^gcr.io/knative-(releases|nightly)/?$" ]] +} + diff --git a/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh b/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh index 5818fab..4ff9475 100755 --- a/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh +++ b/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh @@ -20,42 +20,213 @@ source $(dirname ${BASH_SOURCE})/library.sh # Extensions or file patterns that don't require presubmit tests. -readonly NO_PRESUBMIT_FILES=(\.md \.png ^OWNERS ^OWNERS_ALIASES) +readonly NO_PRESUBMIT_FILES=(\.png \.gitignore \.gitattributes ^OWNERS ^OWNERS_ALIASES ^AUTHORS) -# Options set by command-line flags. -RUN_BUILD_TESTS=0 -RUN_UNIT_TESTS=0 -RUN_INTEGRATION_TESTS=0 -EMIT_METRICS=0 +# Flag if this is a presubmit run or not. +[[ IS_PROW && -n "${PULL_PULL_SHA}" ]] && IS_PRESUBMIT=1 || IS_PRESUBMIT=0 +readonly IS_PRESUBMIT + +# List of changed files on presubmit, LF separated. +CHANGED_FILES="" + +# Flags that this PR is exempt of presubmit tests. +IS_PRESUBMIT_EXEMPT_PR=0 + +# Flags that this PR contains only changes to documentation. +IS_DOCUMENTATION_PR=0 + +# Returns true if PR only contains the given file regexes. +# Parameters: $1 - file regexes, space separated. +function pr_only_contains() { + [[ -z "$(echo "${CHANGED_FILES}" | grep -v \(${1// /\\|}\)$))" ]] +} + +# List changed files in the current PR. +# This is implemented as a function so it can be mocked in unit tests. +function list_changed_files() { + /workspace/githubhelper -list-changed-files +} + +# Initialize flags and context for presubmit tests: +# CHANGED_FILES, IS_PRESUBMIT_EXEMPT_PR and IS_DOCUMENTATION_PR. +function initialize_environment() { + CHANGED_FILES="" + IS_PRESUBMIT_EXEMPT_PR=0 + IS_DOCUMENTATION_PR=0 + (( ! IS_PRESUBMIT )) && return + CHANGED_FILES="$(list_changed_files)" + if [[ -n "${CHANGED_FILES}" ]]; then + echo -e "Changed files in commit ${PULL_PULL_SHA}:\n${CHANGED_FILES}" + local no_presubmit_files="${NO_PRESUBMIT_FILES[*]}" + pr_only_contains "${no_presubmit_files}" && IS_PRESUBMIT_EXEMPT_PR=1 + pr_only_contains "\.md ${no_presubmit_files}" && IS_DOCUMENTATION_PR=1 + else + header "NO CHANGED FILES REPORTED, ASSUMING IT'S AN ERROR AND RUNNING TESTS ANYWAY" + fi + readonly CHANGED_FILES + readonly IS_DOCUMENTATION_PR + readonly IS_PRESUBMIT_EXEMPT_PR +} -# Exit presubmit tests if only documentation files were changed. -function exit_if_presubmit_not_required() { - if [[ -n "${PULL_PULL_SHA}" ]]; then - # On a presubmit job - local changes="$(/workspace/githubhelper -list-changed-files)" - if [[ -z "${changes}" ]]; then - header "NO CHANGED FILES REPORTED, ASSUMING IT'S AN ERROR AND RUNNING TESTS ANYWAY" - return +# Display a pass/fail banner for a test group. +# Parameters: $1 - test group name (e.g., build) +# $2 - result (0=passed, 1=failed) +function results_banner() { + local result + [[ $2 -eq 0 ]] && result="PASSED" || result="FAILED" + header "$1 tests ${result}" +} + +# Run build tests. If there's no `build_tests` function, run the default +# build test runner. +function run_build_tests() { + (( ! RUN_BUILD_TESTS )) && return 0 + header "Running build tests" + local failed=0 + # Run pre-build tests, if any + if function_exists pre_build_tests; then + pre_build_tests || failed=1 + fi + # Don't run build tests if pre-build tests failed + if (( ! failed )); then + if function_exists build_tests; then + build_tests || failed=1 + else + default_build_test_runner || failed=1 fi - local no_presubmit_pattern="${NO_PRESUBMIT_FILES[*]}" - local no_presubmit_pattern="\(${no_presubmit_pattern// /\\|}\)$" - echo -e "Changed files in commit ${PULL_PULL_SHA}:\n${changes}" - if [[ -z "$(echo "${changes}" | grep -v ${no_presubmit_pattern})" ]]; then - # Nothing changed other than files that don't require presubmit tests - header "Commit only contains changes that don't affect tests, skipping" - exit 0 + fi + # Don't run post-build tests if pre/build tests failed + if function_exists post_build_tests; then + post_build_tests || failed=1 + fi + results_banner "Build" ${failed} + return ${failed} +} + +# Default build test runner that: +# * lint and link check markdown files +# * `go build` on the entire repo +# * run `/hack/verify-codegen.sh` (if it exists) +# * check licenses in `/cmd` (if it exists) +function default_build_test_runner() { + local failed=0 + # Ignore markdown files in /vendor + local mdfiles="$(echo "${CHANGED_FILES}" | grep \.md$ | grep -v ^vendor/)" + if [[ -n "${mdfiles}" ]]; then + subheader "Linting the markdown files" + lint_markdown ${mdfiles} || failed=1 + subheader "Checking links in the markdown files" + check_links_in_markdown ${mdfiles} || failed=1 + fi + # For documentation PRs, just check the md files + (( IS_DOCUMENTATION_PR )) && return ${failed} + # Ensure all the code builds + subheader "Checking that go code builds" + go build -v ./... || failed=1 + # Get all build tags in go code (ignore /vendor) + local tags="$(grep -r '// +build' . \ + | grep -v '^./vendor/' | cut -f3 -d' ' | sort | uniq | tr '\n' ' ')" + if [[ -n "${tags}" ]]; then + go test -run=^$ -tags="${tags}" ./... || failed=1 + fi + if [[ -f ./hack/verify-codegen.sh ]]; then + subheader "Checking autogenerated code is up-to-date" + ./hack/verify-codegen.sh || failed=1 + fi + # Check that we don't have any forbidden licenses in our images. + if [[ -d ./cmd ]]; then + subheader "Checking for forbidden licenses" + check_licenses ./cmd/* || failed=1 + fi + return ${failed} +} + +# Run unit tests. If there's no `unit_tests` function, run the default +# unit test runner. +function run_unit_tests() { + (( ! RUN_UNIT_TESTS )) && return 0 + header "Running unit tests" + local failed=0 + # Run pre-unit tests, if any + if function_exists pre_unit_tests; then + pre_unit_tests || failed=1 + fi + # Don't run unit tests if pre-unit tests failed + if (( ! failed )); then + if function_exists unit_tests; then + unit_tests || failed=1 + else + default_unit_test_runner || failed=1 fi fi + # Don't run post-unit tests if pre/unit tests failed + if function_exists post_unit_tests; then + post_unit_tests || failed=1 + fi + results_banner "Unit" ${failed} + return ${failed} +} + +# Default unit test runner that runs all go tests in the repo. +function default_unit_test_runner() { + report_go_test ./... } -function abort() { - echo "error: $@" - exit 1 +# Run integration tests. If there's no `integration_tests` function, run the +# default integration test runner. +function run_integration_tests() { + # Don't run integration tests if not requested OR on documentation PRs + (( ! RUN_INTEGRATION_TESTS )) && return 0 + (( IS_DOCUMENTATION_PR )) && return 0 + header "Running integration tests" + local failed=0 + # Run pre-integration tests, if any + if function_exists pre_integration_tests; then + pre_integration_tests || failed=1 + fi + # Don't run integration tests if pre-integration tests failed + if (( ! failed )); then + if function_exists integration_tests; then + integration_tests || failed=1 + else + default_integration_test_runner || failed=1 + fi + fi + # Don't run integration tests if pre/integration tests failed + if (( ! failed )) && function_exists post_integration_tests; then + post_integration_tests || failed=1 + fi + results_banner "Integration" ${failed} + return ${failed} +} + +# Default integration test runner that runs all `test/e2e-*tests.sh`. +function default_integration_test_runner() { + local options="" + local failed=0 + (( EMIT_METRICS )) && options="--emit-metrics" + for e2e_test in $(find test/ -name e2e-*tests.sh); do + echo "Running integration test ${e2e_test}" + if ! ${e2e_test} ${options}; then + failed=1 + fi + done + return ${failed} } +# Options set by command-line flags. +RUN_BUILD_TESTS=0 +RUN_UNIT_TESTS=0 +RUN_INTEGRATION_TESTS=0 +EMIT_METRICS=0 + # Process flags and run tests accordingly. function main() { - exit_if_presubmit_not_required + initialize_environment + if (( IS_PRESUBMIT_EXEMPT_PR )) && (( ! IS_DOCUMENTATION_PR )); then + header "Commit only contains changes that don't require tests, skipping" + exit 0 + fi # Show the version of the tools we're using if (( IS_PROW )); then @@ -70,6 +241,12 @@ function main() { go version echo ">> git version" git version + echo ">> bazel version" + bazel version 2> /dev/null + if [[ "${DOCKER_IN_DOCKER_ENABLED}" == "true" ]]; then + echo ">> docker version" + docker version + fi fi [[ -z $1 ]] && set -- "--all-tests" @@ -117,45 +294,9 @@ function main() { ${TEST_TO_RUN} || failed=1 fi - if (( RUN_BUILD_TESTS )); then - build_tests || failed=1 - fi - if (( RUN_UNIT_TESTS )); then - unit_tests || failed=1 - fi - if (( RUN_INTEGRATION_TESTS )); then - local e2e_failed=0 - # Run pre-integration tests, if any - if function_exists pre_integration_tests; then - if ! pre_integration_tests; then - failed=1 - e2e_failed=1 - fi - fi - # Don't run integration tests if pre-integration tests failed - if (( ! e2e_failed )); then - if function_exists integration_tests; then - if ! integration_tests; then - failed=1 - e2e_failed=1 - fi - else - local options="" - (( EMIT_METRICS )) && options="--emit-metrics" - for e2e_test in ./test/e2e-*tests.sh; do - echo "Running integration test ${e2e_test}" - if ! ${e2e_test} ${options}; then - failed=1 - e2e_failed=1 - fi - done - fi - fi - # Don't run post-integration - if (( ! e2e_failed )) && function_exists post_integration_tests; then - post_integration_tests || failed=1 - fi - fi + run_build_tests || failed=1 + run_unit_tests || failed=1 + run_integration_tests || failed=1 exit ${failed} } diff --git a/vendor/github.com/knative/test-infra/scripts/release.sh b/vendor/github.com/knative/test-infra/scripts/release.sh index cbde3c6..f71fb85 100755 --- a/vendor/github.com/knative/test-infra/scripts/release.sh +++ b/vendor/github.com/knative/test-infra/scripts/release.sh @@ -19,33 +19,46 @@ source $(dirname ${BASH_SOURCE})/library.sh +# GitHub upstream. +readonly KNATIVE_UPSTREAM="https://github.com/knative/${REPO_NAME}" + # Simple banner for logging purposes. # Parameters: $1 - message to display. function banner() { make_banner "@" "$1" } -# Tag images in the yaml file with a tag. If not tag is passed, does nothing. +# Tag images in the yaml file if $TAG is not empty. +# $KO_DOCKER_REPO is the registry containing the images to tag with $TAG. # Parameters: $1 - yaml file to parse for images. -# $2 - registry where the images are stored. -# $3 - tag to apply (optional). function tag_images_in_yaml() { - [[ -z $3 ]] && return 0 - local src_dir="${GOPATH}/src/" - local BASE_PATH="${REPO_ROOT_DIR/$src_dir}" - echo "Tagging images under '${BASE_PATH}' with $3" - for image in $(grep -o "$2/${BASE_PATH}/[a-z\./-]\+@sha256:[0-9a-f]\+" $1); do - gcloud -q container images add-tag ${image} ${image%%@*}:$3 + [[ -z ${TAG} ]] && return 0 + local SRC_DIR="${GOPATH}/src/" + local DOCKER_BASE="${KO_DOCKER_REPO}/${REPO_ROOT_DIR/$SRC_DIR}" + echo "Tagging images under '${DOCKER_BASE}' with ${TAG}" + for image in $(grep -o "${DOCKER_BASE}/[a-z\./-]\+@sha256:[0-9a-f]\+" $1); do + gcloud -q container images add-tag ${image} ${image%%@*}:${TAG} + + # Georeplicate to {us,eu,asia}.gcr.io + gcloud -q container images add-tag ${image} us.${image%%@*}:${TAG} + gcloud -q container images add-tag ${image} eu.${image%%@*}:${TAG} + gcloud -q container images add-tag ${image} asia.${image%%@*}:${TAG} done } -# Copy the given yaml file to a GCS bucket. Image is tagged :latest, and optionally :$2. +# Copy the given yaml file to the $RELEASE_GCS_BUCKET bucket's "latest" directory. +# If $TAG is not empty, also copy it to $RELEASE_GCS_BUCKET bucket's "previous" directory. # Parameters: $1 - yaml file to copy. -# $2 - destination bucket name. -# $3 - tag to apply (optional). function publish_yaml() { - gsutil cp $1 gs://$2/latest/ - [[ -n $3 ]] && gsutil cp $1 gs://$2/previous/$3/ || true + function verbose_gsutil_cp { + local DEST="gs://${RELEASE_GCS_BUCKET}/$2/" + echo "Publishing $1 to ${DEST}" + gsutil cp $1 ${DEST} + } + verbose_gsutil_cp $1 latest + if [[ -n ${TAG} ]]; then + verbose_gsutil_cp $1 previous/${TAG} + fi } # These are global environment variables. @@ -57,11 +70,98 @@ TAG="" RELEASE_VERSION="" RELEASE_NOTES="" RELEASE_BRANCH="" +RELEASE_GCS_BUCKET="" KO_FLAGS="" +export KO_DOCKER_REPO="" +export GITHUB_TOKEN="" + +# Convenience function to run the hub tool. +# Parameters: $1..$n - arguments to hub. +function hub_tool() { + run_go_tool github.com/github/hub hub $@ +} + +# Return the master version of a release. +# For example, "v0.2.1" returns "0.2" +# Parameters: $1 - release version label. +function master_version() { + local release="${1//v/}" + local tokens=(${release//\./ }) + echo "${tokens[0]}.${tokens[1]}" +} -function abort() { - echo "error: $@" - exit 1 +# Return the release build number of a release. +# For example, "v0.2.1" returns "1". +# Parameters: $1 - release version label. +function release_build_number() { + local tokens=(${1//\./ }) + echo "${tokens[2]}" +} + +# Setup the repository upstream, if not set. +function setup_upstream() { + # hub and checkout need the upstream URL to be set + # TODO(adrcunha): Use "git remote get-url" once available on Prow. + local upstream="$(git config --get remote.upstream.url)" + echo "Remote upstream URL is '${upstream}'" + if [[ -z "${upstream}" ]]; then + echo "Setting remote upstream URL to '${KNATIVE_UPSTREAM}'" + git remote add upstream ${KNATIVE_UPSTREAM} + fi +} + +# Fetch the release branch, so we can check it out. +function setup_branch() { + [[ -z "${RELEASE_BRANCH}" ]] && return + git fetch ${KNATIVE_UPSTREAM} ${RELEASE_BRANCH}:upstream/${RELEASE_BRANCH} +} + +# Setup version, branch and release notes for a "dot" release. +function prepare_dot_release() { + echo "Dot release requested" + TAG_RELEASE=1 + PUBLISH_RELEASE=1 + # List latest release + local releases # don't combine with the line below, or $? will be 0 + releases="$(hub_tool release)" + [[ $? -eq 0 ]] || abort "cannot list releases" + # If --release-branch passed, restrict to that release + if [[ -n "${RELEASE_BRANCH}" ]]; then + local version_filter="v${RELEASE_BRANCH##release-}" + echo "Dot release will be generated for ${version_filter}" + releases="$(echo "${releases}" | grep ^${version_filter})" + fi + local last_version="$(echo "${releases}" | grep '^v[0-9]\+\.[0-9]\+\.[0-9]\+$' | sort -r | head -1)" + [[ -n "${last_version}" ]] || abort "no previous release exist" + if [[ -z "${RELEASE_BRANCH}" ]]; then + echo "Last release is ${last_version}" + # Determine branch + local major_minor_version="$(master_version ${last_version})" + RELEASE_BRANCH="release-${major_minor_version}" + echo "Last release branch is ${RELEASE_BRANCH}" + fi + # Ensure there are new commits in the branch, otherwise we don't create a new release + setup_branch + local last_release_commit="$(git rev-list -n 1 ${last_version})" + local release_branch_commit="$(git rev-list -n 1 upstream/${RELEASE_BRANCH})" + [[ -n "${last_release_commit}" ]] || abort "cannot get last release commit" + [[ -n "${release_branch_commit}" ]] || abort "cannot get release branch last commit" + if [[ "${last_release_commit}" == "${release_branch_commit}" ]]; then + echo "*** Branch ${RELEASE_BRANCH} is at commit ${release_branch_commit}" + echo "*** Branch ${RELEASE_BRANCH} has no new cherry-picks since release ${last_version}" + echo "*** No dot release will be generated, as no changes exist" + exit 0 + fi + # Create new release version number + local last_build="$(release_build_number ${last_version})" + RELEASE_VERSION="${major_minor_version}.$(( last_build + 1 ))" + echo "Will create release ${RELEASE_VERSION} at commit ${release_branch_commit}" + # If --release-notes not used, copy from the latest release + if [[ -z "${RELEASE_NOTES}" ]]; then + RELEASE_NOTES="$(mktemp)" + hub_tool release show -f "%b" ${last_version} > ${RELEASE_NOTES} + echo "Release notes from ${last_version} copied to ${RELEASE_NOTES}" + fi } # Parses flags and sets environment variables accordingly. @@ -71,42 +171,71 @@ function parse_flags() { RELEASE_NOTES="" RELEASE_BRANCH="" KO_FLAGS="-P" + KO_DOCKER_REPO="gcr.io/knative-nightly" + RELEASE_GCS_BUCKET="knative-nightly/${REPO_NAME}" + GITHUB_TOKEN="" + local has_gcr_flag=0 + local has_gcs_flag=0 + local is_dot_release=0 + cd ${REPO_ROOT_DIR} while [[ $# -ne 0 ]]; do local parameter=$1 - case $parameter in + case ${parameter} in --skip-tests) SKIP_TESTS=1 ;; --tag-release) TAG_RELEASE=1 ;; --notag-release) TAG_RELEASE=0 ;; --publish) PUBLISH_RELEASE=1 ;; --nopublish) PUBLISH_RELEASE=0 ;; - --version) + --dot-release) is_dot_release=1 ;; + *) + [[ $# -ge 2 ]] || abort "missing parameter after $1" shift - [[ $# -ge 1 ]] || abort "missing version after --version" - [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || abort "version format must be '[0-9].[0-9].[0-9]'" - RELEASE_VERSION=$1 - ;; - --branch) - shift - [[ $# -ge 1 ]] || abort "missing branch after --commit" - [[ $1 =~ ^release-[0-9]+\.[0-9]+$ ]] || abort "branch name must be 'release-[0-9].[0-9]'" - RELEASE_BRANCH=$1 - ;; - --release-notes) - shift - [[ $# -ge 1 ]] || abort "missing release notes file after --release-notes" - [[ ! -f "$1" ]] && abort "file $1 doesn't exist" - RELEASE_NOTES=$1 - ;; - *) abort "unknown option ${parameter}" ;; + case ${parameter} in + --github-token) + [[ ! -f "$1" ]] && abort "file $1 doesn't exist" + GITHUB_TOKEN="$(cat $1)" + [[ -n "${GITHUB_TOKEN}" ]] || abort "file $1 is empty" + ;; + --release-gcr) + KO_DOCKER_REPO=$1 + has_gcr_flag=1 + ;; + --release-gcs) + RELEASE_GCS_BUCKET=$1 + has_gcs_flag=1 + ;; + --version) + [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || abort "version format must be '[0-9].[0-9].[0-9]'" + RELEASE_VERSION=$1 + ;; + --branch) + [[ $1 =~ ^release-[0-9]+\.[0-9]+$ ]] || abort "branch name must be 'release-[0-9].[0-9]'" + RELEASE_BRANCH=$1 + ;; + --release-notes) + [[ ! -f "$1" ]] && abort "file $1 doesn't exist" + RELEASE_NOTES=$1 + ;; + *) abort "unknown option ${parameter}" ;; + esac esac shift done + # Setup dot releases + if (( is_dot_release )); then + setup_upstream + prepare_dot_release + fi + # Update KO_DOCKER_REPO and KO_FLAGS if we're not publishing. if (( ! PUBLISH_RELEASE )); then + (( has_gcr_flag )) && echo "Not publishing the release, GCR flag is ignored" + (( has_gcs_flag )) && echo "Not publishing the release, GCS flag is ignored" KO_DOCKER_REPO="ko.local" KO_FLAGS="-L ${KO_FLAGS}" + RELEASE_GCS_BUCKET="" fi if (( TAG_RELEASE )); then @@ -131,6 +260,8 @@ function parse_flags() { readonly RELEASE_VERSION readonly RELEASE_NOTES readonly RELEASE_BRANCH + readonly RELEASE_GCS_BUCKET + readonly KO_DOCKER_REPO } # Run tests (unless --skip-tests was passed). Conveniently displays a banner indicating so. @@ -149,8 +280,29 @@ function run_validation_tests() { # Initialize everything (flags, workspace, etc) for a release. function initialize() { parse_flags $@ + # Log what will be done and where. + banner "Release configuration" + echo "- Destination GCR: ${KO_DOCKER_REPO}" + (( SKIP_TESTS )) && echo "- Tests will NOT be run" || echo "- Tests will be run" + if (( TAG_RELEASE )); then + echo "- Artifacts will tagged '${TAG}'" + else + echo "- Artifacts WILL NOT be tagged" + fi + if (( PUBLISH_RELEASE )); then + echo "- Release WILL BE published to '${RELEASE_GCS_BUCKET}'" + else + echo "- Release will not be published" + fi + if (( BRANCH_RELEASE )); then + echo "- Release WILL BE branched from '${RELEASE_BRANCH}'" + fi + [[ -n "${RELEASE_NOTES}" ]] && echo "- Release notes are generated from '${RELEASE_NOTES}'" + # Checkout specific branch, if necessary if (( BRANCH_RELEASE )); then + setup_upstream + setup_branch git checkout upstream/${RELEASE_BRANCH} || abort "cannot checkout branch ${RELEASE_BRANCH}" fi } @@ -174,8 +326,11 @@ function branch_release() { cat ${RELEASE_NOTES} >> ${description} fi git tag -a ${TAG} -m "${title}" - git push $(git remote get-url upstream) tag ${TAG} - run_go_tool github.com/github/hub hub release create \ + local repo_url="${KNATIVE_UPSTREAM}" + [[ -n "${GITHUB_TOKEN}}" ]] && repo_url="${repo_url/:\/\//:\/\/${GITHUB_TOKEN}@}" + hub_tool push ${repo_url} tag ${TAG} + + hub_tool release create \ --prerelease \ ${attachments[@]} \ --file=${description} \