diff options
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/cirrus/logformatter | 105 | ||||
-rwxr-xr-x | contrib/cirrus/logformatter.t | 10 | ||||
-rw-r--r-- | contrib/imgprune/Dockerfile | 7 | ||||
-rw-r--r-- | contrib/imgprune/README.md | 11 | ||||
-rwxr-xr-x | contrib/imgprune/entrypoint.sh | 106 | ||||
-rw-r--r-- | contrib/imgts/Dockerfile | 20 | ||||
-rw-r--r-- | contrib/imgts/README.md | 11 | ||||
-rwxr-xr-x | contrib/imgts/entrypoint.sh | 23 | ||||
-rw-r--r-- | contrib/imgts/google-cloud-sdk.repo | 8 | ||||
-rw-r--r-- | contrib/imgts/lib_entrypoint.sh | 49 | ||||
-rw-r--r-- | contrib/upldrel/Dockerfile | 9 | ||||
-rw-r--r-- | contrib/upldrel/README.md | 9 | ||||
-rwxr-xr-x | contrib/upldrel/entrypoint.sh | 27 |
13 files changed, 107 insertions, 288 deletions
diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter index f97638b6f..2ab8aa117 100755 --- a/contrib/cirrus/logformatter +++ b/contrib/cirrus/logformatter @@ -31,6 +31,12 @@ our $CSS = <<'END_CSS'; /* wrap long lines - don't require user to scroll right */ pre { line-break: normal; overflow-wrap: normal; white-space: pre-wrap; } +/* synopsis table at top */ +table.synopsis { border: none; border-collapse: collapse; margin-left: 2em; margin-top: 2ex; } +.synopsis th { font-weight: normal; font-size: 110%; text-align: right; } +.synopsis td { font-weight: bold; font-size: 120%; font-family: monospace; } + +/* test results */ .boring { color: #999; } .timestamp { color: #999; } .log-debug { color: #999; } @@ -171,9 +177,20 @@ window.addEventListener("load", scrollToBottom, false); </script> </head> <body> -<pre> <!-- begin processed output --> END_HTML + # Synopsis of this job: show job environment, links to PR and Cirrus + print { $out_fh } "<h2>Synopsis</h2>\n<hr/>\n", + job_synopsis($test_name), "<hr/>\n"; + + # FOR DEBUGGING: dump environment, but in HTML comments to not clutter + print { $out_fh } "<!-- Environment: -->\n"; + for my $e (sort keys %ENV) { + my $val = escapeHTML($ENV{$e}); + $val =~ s/--/--/g; # double dash not valid in comments + printf { $out_fh } "<!-- %-20s %s -->\n", $e, $val; + } + # State variables my $previous_timestamp = ''; # timestamp of previous line my $cirrus_task; # Cirrus task number, used for linking @@ -185,6 +202,8 @@ END_HTML my $looks_like_bats; # binary flag: for detecting BATS results my %bats_count; # For summary line: count of pass/fail/skip + print { $out_fh } "<pre> <!-- begin processed output -->\n"; + # Main loop: read input, one line at a time, and write out reformatted LINE: while (my $line = <STDIN>) { @@ -232,8 +251,9 @@ END_HTML my $css; # Readability: /long/path/to/podman -> podman (hover for full path) - $line =~ s{^(#\s+(#|\$)\s+)(\S+/)(podman\S*)\s} - {$1<span title="$3$4">$4</span> }; + # Also make it boldface, to make commands stand out + $line =~ s{^(#\s+(#|\$)\s+)(\S+/)(podman\S*)(\s.*)} + {$1<b><span title="$3$4">$4</span>$5</b>}; if ($line =~ /^ok\s.*\s# skip/) { $css = 'skipped' } elsif ($line =~ /^ok\s/) { $css = 'passed' } @@ -470,6 +490,83 @@ sub make_id { } +############################################################################### +# BEGIN job_synopsis and related helpers + +################## +# job_synopsis # Job details, links to github/cirrus +################## +sub job_synopsis { + my $subtest_name = shift; # e.g. integration_test + + my $s = <<"END_SYNOPSIS"; +<table class="synopsis"> +END_SYNOPSIS + + # PR 1234 - title of the pr + my $pr_title = escapeHTML(_env_replace("{CIRRUS_CHANGE_TITLE}")); + $s .= _tr("Github PR", sprintf("%s - %s", + _a("{CIRRUS_PR}", "https://{CIRRUS_REPO_CLONE_HOST}/{CIRRUS_REPO_FULL_NAME}/pull/{CIRRUS_PR}"), + $pr_title)); + + # PR author, if signed-off-by + if (my $msg = _env_replace("{CIRRUS_COMMIT_MESSAGE}")) { + while ($msg =~ /^Signed-off-by:\s+(\S.*\S)$/gmi) { + $s .= _tr("Author", escapeHTML($1)); + } + } + + # eg "test fedora", "special_testing_rootless" + my $test_name = _env_replace("{CIRRUS_TASK_NAME}"); + if (my $rcli = $ENV{RCLI}) { + $test_name .= " [remote]" if $rcli eq 'true'; + } + else { + $test_name .= " [no RCLI; cannot determine remote/local]"; + } + $s .= _tr("Test name", $test_name); + + # Subtest, e.g. system_test + $s .= _tr("Subtest", $subtest_name); + + # Link to further Cirrus results, e.g. other runs. + # Build is mostly boring, it's usually TASK that we want to see. + $s .= _tr("Cirrus Build ID", "<small>" . _a("{CIRRUS_BUILD_ID}", "https://cirrus-ci.com/build/{CIRRUS_BUILD_ID}") . "</small>"); + $s .= _tr("Cirrus <b>Task</b> ID", _a("{CIRRUS_TASK_ID}", "https://cirrus-ci.com/task/{CIRRUS_TASK_ID}")); + + # "none", "rootless" + $s .= _tr("Special mode", _env_replace("{SPECIALMODE}")); + + $s .= "</table>\n"; + return $s; +} + + +sub _tr { + my ($th, $td) = @_; + return "<tr><th>$th:</th><td>$td</td></tr>\n"; +} + +sub _a { + my ($name, $href) = map { _env_replace($_) } @_; + + if ($href =~ /UNDEFINED/) { + return "$name ($href)"; + } + return "<a href='$href'>$name</a>"; +} + +sub _env_replace { + my $s_in = shift; + + $s_in =~ s[\{(.*?)\}][$ENV{$1} || "[$1 UNDEFINED]"]ge; + + return $s_in; +} + +# END job_synopsis and related helpers +############################################################################### +# BEGIN html-formatting helpers sub escapeHTML { my $s = shift; @@ -492,5 +589,7 @@ sub unescapeHTML { return $s; } +# END html-formatting helpers +############################################################################### 1; diff --git a/contrib/cirrus/logformatter.t b/contrib/cirrus/logformatter.t index 2075bff96..bd4179b5e 100755 --- a/contrib/cirrus/logformatter.t +++ b/contrib/cirrus/logformatter.t @@ -96,7 +96,7 @@ ok 4 blah <span class='bats-passed'><a name='t--00001'>ok 1 hi</a></span> <span class='bats-skipped'><a name='t--00002'>ok 2 bye # skip no reason</a></span> <span class='bats-failed'><a name='t--00003'>not ok 3 fail</a></span> -<span class='bats-log'># $ <span title="/path/to/podman">podman</span> foo -bar</span> +<span class='bats-log'># $ <b><span title="/path/to/podman">podman</span> foo -bar</b></span> <span class='bats-log-esm'># #| FAIL: exit code is 123; expected 321</span> <span class='bats-passed'><a name='t--00004'>ok 4 blah</a></span> <hr/><span class='bats-summary'>Summary: <span class='bats-passed'>2 Passed</span>, <span class='bats-failed'>1 Failed</span>, <span class='bats-skipped'>1 Skipped</span>. Total tests: 4</span> @@ -147,11 +147,11 @@ $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP} <pre> <span class="timestamp">[+0103s] </span>Podman pod restart <span class="timestamp"> </span><a name='t--podman-pod-restart-single-empty-pod--1'><h2> podman pod restart single empty pod</h2></a> -<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/libpod/test/e2e/pod_restart_test.go:41</a> +<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/podman/test/e2e/pod_restart_test.go:41</a> <span class="timestamp"> </span>[BeforeEach] Podman pod restart -<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L18'>/containers/libpod/test/e2e/pod_restart_test.go:18</a> +<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L18'>/containers/podman/test/e2e/pod_restart_test.go:18</a> <span class="timestamp"> </span>[It] podman pod restart single empty pod -<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/libpod/test/e2e/pod_restart_test.go:41</a> +<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/podman/test/e2e/pod_restart_test.go:41</a> <span class="timestamp"> </span>Running: <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run @@ -176,7 +176,7 @@ $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP} <span class="timestamp"> </span><span class='log-warn'>Error: no containers in pod 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 have no dependencies, cannot start pod: no such container</span> <span class="timestamp"> </span>output: <span class="timestamp"> </span>[AfterEach] Podman pod restart -<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L28'>/containers/libpod/test/e2e/pod_restart_test.go:28</a> +<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L28'>/containers/podman/test/e2e/pod_restart_test.go:28</a> <span class="timestamp"> </span>Running: <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run diff --git a/contrib/imgprune/Dockerfile b/contrib/imgprune/Dockerfile deleted file mode 100644 index b0dc77da5..000000000 --- a/contrib/imgprune/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM quay.io/libpod/imgts:latest - -RUN yum -y update && \ - yum clean all - -COPY /contrib/imgprune/entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod 755 /usr/local/bin/entrypoint.sh diff --git a/contrib/imgprune/README.md b/contrib/imgprune/README.md deleted file mode 100644 index 48abc2028..000000000 --- a/contrib/imgprune/README.md +++ /dev/null @@ -1,11 +0,0 @@ -![PODMAN logo](../../logo/podman-logo-source.svg) - -A container image for maintaining the collection of -VM images used by CI/CD on this project and several others. -Acts upon metadata maintained by the imgts container. - -Example build (from repository root): - -```bash -sudo podman build -t $IMAGE_NAME -f contrib/imgprune/Dockerfile . -``` diff --git a/contrib/imgprune/entrypoint.sh b/contrib/imgprune/entrypoint.sh deleted file mode 100755 index fd80d9b26..000000000 --- a/contrib/imgprune/entrypoint.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source /usr/local/bin/lib_entrypoint.sh - -req_env_var GCPJSON GCPNAME GCPPROJECT IMGNAMES - -unset BASE_IMAGES -# When executing under Cirrus-CI, script have access to current source -LIB="$CIRRUS_WORKING_DIR/$SCRIPT_BASE/lib.sh" -if [[ "$CI" == "true" ]] && [[ -r "$LIB" ]] -then - # Avoid importing anything that might conflict - for env in $(sed -ne 's/^[^#]\+_BASE_IMAGE=/img=/p' "$LIB") - do - eval $env - BASE_IMAGES="$BASE_IMAGES $img" - done -else - # metadata labeling may have broken for some reason in the future - echo "Warning: Running outside of Cirrus-CI, very minor-risk of base-image deletion." -fi - -gcloud_init - -# For safety's sake + limit nr background processes -PRUNE_LIMIT=5 -THEFUTURE=$(date --date='+1 hour' +%s) -TOO_OLD='30 days ago' -THRESHOLD=$(date --date="$TOO_OLD" +%s) -# Format Ref: https://cloud.google.com/sdk/gcloud/reference/topic/formats -FORMAT='value[quote](name,selfLink,creationTimestamp,labels)' -PROJRE="/v1/projects/$GCPPROJECT/global/" -RECENTLY=$(date --date='3 days ago' --iso-8601=date) -# Filter Ref: https://cloud.google.com/sdk/gcloud/reference/topic/filters -FILTER="selfLink~$PROJRE AND creationTimestamp<$RECENTLY AND NOT name=($IMGNAMES $BASE_IMAGES)" -TODELETE=$(mktemp -p '' todelete.XXXXXX) -IMGCOUNT=$(mktemp -p '' imgcount.XXXXXX) - -# Search-loop runs in a sub-process, must store count in file -echo "0" > "$IMGCOUNT" -count_image() { - local count - count=$(<"$IMGCOUNT") - let 'count+=1' - echo "$count" > "$IMGCOUNT" -} - -echo "Using filter: $FILTER" -echo "Searching images for pruning candidates older than $TOO_OLD ($(date --date="$TOO_OLD" --iso-8601=date)):" -$GCLOUD compute images list --format="$FORMAT" --filter="$FILTER" | \ - while read name selfLink creationTimestamp labels - do - count_image - created_ymd=$(date --date=$creationTimestamp --iso-8601=date) - last_used=$(egrep --only-matching --max-count=1 'last-used=[[:digit:]]+' <<< $labels || true) - markmsgpfx="Marking $name (created $created_ymd) for deletion" - if [[ -z "$last_used" ]] - then # image pre-dates addition of tracking labels - echo "$markmsgpfx: Missing 'last-used' metadata, labels: '$labels'" - echo "$name" >> $TODELETE - continue - fi - - last_used_timestamp=$(date --date=@$(cut -d= -f2 <<< $last_used || true) +%s || true) - last_used_ymd=$(date --date=@$last_used_timestamp --iso-8601=date) - if [[ -z "$last_used_timestamp" ]] || [[ "$last_used_timestamp" -ge "$THEFUTURE" ]] - then - echo "$markmsgpfx: Missing or invalid last-used timestamp: '$last_used_timestamp'" - echo "$name" >> $TODELETE - continue - fi - - if [[ "$last_used_timestamp" -le "$THRESHOLD" ]] - then - echo "$markmsgpfx: Used over $TOO_OLD on $last_used_ymd" - echo "$name" >> $TODELETE - continue - fi - done - -COUNT=$(<"$IMGCOUNT") -echo "########################################################################" -echo "Deleting up to $PRUNE_LIMIT images marked ($(wc -l < $TODELETE)) of all searched ($COUNT):" - -# Require a minimum number of images to exist -NEED="$[$PRUNE_LIMIT*2]" -if [[ "$COUNT" -lt "$NEED" ]] -then - die 0 Safety-net Insufficient images \($COUNT\) to process deletions \($NEED\) - exit 0 -fi - -for image_name in $(sort --random-sort $TODELETE | tail -$PRUNE_LIMIT) -do - if echo "$IMGNAMES $BASE_IMAGES" | grep -q "$image_name" - then - # double-verify in-use images were filtered out in search loop above - die 8 FATAL ATTEMPT TO DELETE IN-USE IMAGE \'$image_name\' - THIS SHOULD NEVER HAPPEN - fi - echo "Deleting $image_name in parallel..." - $GCLOUD compute images delete $image_name & -done - -wait || true # Nothing to delete: No background jobs diff --git a/contrib/imgts/Dockerfile b/contrib/imgts/Dockerfile deleted file mode 100644 index deaadb899..000000000 --- a/contrib/imgts/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM centos:7 - -# Only needed for installing build-time dependencies -COPY /contrib/imgts/google-cloud-sdk.repo /etc/yum.repos.d/google-cloud-sdk.repo -RUN yum -y update && \ - yum -y install epel-release && \ - yum -y install google-cloud-sdk && \ - yum clean all - -ENV GCPJSON="__unknown__" \ - GCPNAME="__unknown__" \ - GCPPROJECT="__unknown__" \ - IMGNAMES="__unknown__" \ - BUILDID="__unknown__" \ - REPOREF="__unknown__" - -COPY ["/contrib/imgts/entrypoint.sh", "/contrib/imgts/lib_entrypoint.sh", "/usr/local/bin/"] -RUN chmod 755 /usr/local/bin/entrypoint.sh - -ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/contrib/imgts/README.md b/contrib/imgts/README.md deleted file mode 100644 index ad5ed4172..000000000 --- a/contrib/imgts/README.md +++ /dev/null @@ -1,11 +0,0 @@ -![PODMAN logo](../../logo/podman-logo-source.svg) - -A container image for tracking automation metadata. -Currently this is used to update last-used timestamps on -VM images. - -Example build (from repository root): - -```bash -sudo podman build -t $IMAGE_NAME -f contrib/imgts/Dockerfile . -``` diff --git a/contrib/imgts/entrypoint.sh b/contrib/imgts/entrypoint.sh deleted file mode 100755 index b089e1e9b..000000000 --- a/contrib/imgts/entrypoint.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source /usr/local/bin/lib_entrypoint.sh - -req_env_var GCPJSON GCPNAME GCPPROJECT IMGNAMES BUILDID REPOREF - -gcloud_init - -ARGS=" - --update-labels=last-used=$(date +%s) - --update-labels=build-id=$BUILDID - --update-labels=repo-ref=$REPOREF - --update-labels=project=$GCPPROJECT -" - -for image in $IMGNAMES -do - $GCLOUD compute images update "$image" $ARGS & -done - -wait || echo "Warning: No \$IMGNAMES were specified." diff --git a/contrib/imgts/google-cloud-sdk.repo b/contrib/imgts/google-cloud-sdk.repo deleted file mode 100644 index 45b1e43bb..000000000 --- a/contrib/imgts/google-cloud-sdk.repo +++ /dev/null @@ -1,8 +0,0 @@ -[google-cloud-sdk] -name=Google Cloud SDK -baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64 -enabled=1 -gpgcheck=1 -repo_gpgcheck=1 -gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg - https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg diff --git a/contrib/imgts/lib_entrypoint.sh b/contrib/imgts/lib_entrypoint.sh deleted file mode 100644 index 6eb5cdc2f..000000000 --- a/contrib/imgts/lib_entrypoint.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -set -e - -RED="\e[1;36;41m" -YEL="\e[1;33;44m" -NOR="\e[0m" -SENTINEL="__unknown__" # default set in dockerfile -# Disable all input prompts -# https://cloud.google.com/sdk/docs/scripting-gcloud -GCLOUD="gcloud --quiet" - -die() { - EXIT=$1 - PFX=$2 - shift 2 - MSG="$@" - echo -e "${RED}${PFX}:${NOR} ${YEL}$MSG${NOR}" - [[ "$EXIT" -eq "0" ]] || exit "$EXIT" -} - -# Pass in a list of one or more envariable names; exit non-zero with -# helpful error message if any value is empty -req_env_var() { - for i; do - if [[ -z "${!i}" ]] - then - die 1 FATAL entrypoint.sh requires \$$i to be non-empty. - elif [[ "${!i}" == "$SENTINEL" ]] - then - die 2 FATAL entrypoint.sh requires \$$i to be explicitly set. - fi - done -} - -gcloud_init() { - set +xe - if [[ -n "$1" ]] && [[ -r "$1" ]] - then - TMPF="$1" - else - TMPF=$(mktemp -p '' .$(uuidgen)_XXXX.json) - trap "rm -f $TMPF &> /dev/null" EXIT - echo "$GCPJSON" > $TMPF - fi - $GCLOUD auth activate-service-account --project="$GCPPROJECT" --key-file="$TMPF" || \ - die 5 FATAL auth - rm -f $TMPF &> /dev/null || true # ignore any read-only error -} diff --git a/contrib/upldrel/Dockerfile b/contrib/upldrel/Dockerfile deleted file mode 100644 index 54a58c521..000000000 --- a/contrib/upldrel/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM quay.io/libpod/imgts:latest - -RUN yum -y update && \ - yum -y install unzip && \ - rpm -V unzip && \ - yum clean all - -COPY /contrib/upldrel/entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod 755 /usr/local/bin/entrypoint.sh diff --git a/contrib/upldrel/README.md b/contrib/upldrel/README.md deleted file mode 100644 index 41f5ffef0..000000000 --- a/contrib/upldrel/README.md +++ /dev/null @@ -1,9 +0,0 @@ -![PODMAN logo](../../logo/podman-logo-source.svg) - -A container image for canonical-naming and uploading of -libpod and remote-client archives. Only intended to ever -be used by CI/CD, and depends heavily on an embedded -`release.txt` file produced by `make`. - -Build script: [../cirrus/build_release.sh](../cirrus/build_release.sh) -Upload script: [../cirrus/upload_release_archive.sh](../cirrus/upload_release_archive.sh) diff --git a/contrib/upldrel/entrypoint.sh b/contrib/upldrel/entrypoint.sh deleted file mode 100755 index 6eb1b8f94..000000000 --- a/contrib/upldrel/entrypoint.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source /usr/local/bin/lib_entrypoint.sh - -req_env_var GCPJSON_FILEPATH GCPNAME GCPPROJECT BUCKET FROM_FILEPATH TO_FILENAME - -[[ -r "$FROM_FILEPATH" ]] || \ - die 2 ERROR Cannot read release archive file: "$FROM_FILEPATH" - -[[ -r "$GCPJSON_FILEPATH" ]] || \ - die 3 ERROR Cannot read GCP credentials file: "$GCPJSON_FILEPATH" - -echo "Authenticating to google cloud for upload" -gcloud_init "$GCPJSON_FILEPATH" - -echo "Uploading archive as $TO_FILENAME" -gsutil cp "$FROM_FILEPATH" "gs://$BUCKET/$TO_FILENAME" -[[ -z "$ALSO_FILENAME" ]] || \ - gsutil cp "$FROM_FILEPATH" "gs://$BUCKET/$ALSO_FILENAME" - -echo "." -echo "Release now available for download at:" -echo " https://storage.googleapis.com/$BUCKET/$TO_FILENAME" -[[ -z "$ALSO_FILENAME" ]] || \ - echo " https://storage.googleapis.com/$BUCKET/$ALSO_FILENAME" |