diff --git a/ci/release/README.md b/ci/release/README.md index 4530983e4..10c4c44b2 100644 --- a/ci/release/README.md +++ b/ci/release/README.md @@ -14,6 +14,10 @@ it depends on from ../sub/lib. - ./release.sh is the top level script to generate a new release. Run with --help for usage. +### upload_assets.sh + +- Called by ./release.sh to upload the assets for the release in $VERSION + ## build.sh - ./build.sh builds the release archives for each platform into ./build//*.tar.gz diff --git a/ci/release/_build.sh b/ci/release/_build.sh index db1b27de9..c5170219a 100755 --- a/ci/release/_build.sh +++ b/ci/release/_build.sh @@ -16,4 +16,7 @@ sh_c mkdir -p "$HW_BUILD_DIR/bin" sh_c go build -ldflags "'-X oss.terrastruct.com/d2/lib/version.Version=$VERSION'" \ -o "$HW_BUILD_DIR/bin/d2" ./cmd/d2 -sh_c tar czf "$ARCHIVE" "$HW_BUILD_DIR" +ARCHIVE=$PWD/$ARCHIVE +cd "$(dirname "$HW_BUILD_DIR")" +sh_c tar -czf "$ARCHIVE" "$(basename "$HW_BUILD_DIR")" +cd ->/dev/null diff --git a/ci/release/_install.sh b/ci/release/_install.sh index da48d5f52..19a909f1c 100755 --- a/ci/release/_install.sh +++ b/ci/release/_install.sh @@ -1,10 +1,11 @@ #!/bin/sh set -eu -cd -- "$(dirname "$0")/../.." -. ./ci/sub/lib/log.sh -. ./ci/sub/lib/flag.sh -cd - +cd -- "$(dirname "$0")/../sub/lib" +. ./log.sh +. ./flag.sh +. ./release.sh +cd - >/dev/null help() { arg0="$0" @@ -13,7 +14,7 @@ help() { fi cat </dev/null; then + INSTALLED_VERSION="$(d2 version)" + if [ ! "${FORCE-}" -a "$VERSION" = "$INSTALLED_VERSION" ]; then + log "skipping installation as version $VERSION is already installed." + return 0 + fi + log "uninstalling $INSTALLED_VERSION to install $VERSION" + # uninstall + fi + + install_standalone +} + +install_standalone() { + ARCHIVE="d2-$VERSION-$OS-$ARCH.tar.gz" + log "installing standalone release $ARCHIVE from github" + + VERSION=$(fetch_version_info) + asset_line=$(cat "$CACHE_DIR/$VERSION.json" | grep -n "$ARCHIVE" | cut -d: -f1 | head -n1) + asset_url=$(sed -n $((asset_line-3))p "$CACHE_DIR/$VERSION.json" | sed 's/^.*: "\(.*\)",$/\1/g') + fetch_gh "$asset_url" "$CACHE_DIR/$ARCHIVE" 'application/octet-stream' + + sh_c tar -C "$CACHE_DIR" -xzf "$CACHE_DIR/$ARCHIVE" + sh_c cd "$CACHE_DIR/d2-$VERSION" + + sh_c="sh_c" + if !is_prefix_writable; then + sh_c="sudo_sh_c" + fi + "$sh_c" make install PREFIX="$PREFIX" +} + +uninstall() { + log "uninstalling standalone release d2-$VERSION" + + sh_c cd "$CACHE_DIR/d2-$VERSION" + + sh_c="sh_c" + if !is_prefix_writable; then + sh_c="sudo_sh_c" + fi + "$sh_c" make uninstall PREFIX="$PREFIX" +} + +is_prefix_writable() { + sh_c mkdir -p "$PREFIX" 2>/dev/null || true + # The reason for checking whether bin is writable specifically is that on macOS you have + # /usr/local owned by root but you don't need root to write to its subdirectories which + # is all we want to do. + if [ ! -w "$PREFIX/bin" ]; then + return 0 + fi +} + +cache_dir() { + if [ -n "${XDG_CACHE_HOME-}" ]; then + echo "$XDG_CACHE_HOME/d2/release" + elif [ -n "${HOME-}" ]; then + echo "$HOME/.cache/d2/release" + else + echo "/tmp/d2-cache/release" + fi +} + +fetch_version_info() { + req_version=$VERSION + log "fetching info on version $req_version" + if [ -e "$CACHE_DIR/$req_version.json" ]; then + log "reusing $CACHE_DIR/$req_version.json" + fi + + rm -f "$CACHE_DIR/req_version.json" + if [ "$req_version" = latest ]; then + release_info_url="https://api.github.com/repos/$REPO/releases/$req_version" + else + release_info_url="https://api.github.com/repos/$REPO/releases/tags/$req_version" + fi + fetch_gh "$release_info_url" "$CACHE_DIR/$req_version.json" \ + 'application/json' + VERSION=$(cat "$CACHE_DIR/$req_version.json" | grep -m1 tag_name | sed 's/^.*: "\(.*\)",$/\1/g') + if [ "$req_version" = latest ]; then + mv "$CACHE_DIR/$req_version.json" "$CACHE_DIR/$VERSION.json" + fi + echo "$VERSION" +} + +curl_gh() { + sh_c curl -fL ${GITHUB_TOKEN+"-H \"Authorization: Bearer \$GITHUB_TOKEN\""} "$@" +} + +fetch_gh() { + url=$1 + file=$2 + accept=$3 + + if [ -e "$file" ]; then + log "reusing $file" + return + fi + + curl_gh -#o "$file.inprogress" -C- -H "'Accept: $accept'" "$url" + sh_c mv "$file.inprogress" "$file" } main "$@" diff --git a/ci/release/build.sh b/ci/release/build.sh index 78bc6ab58..8aaec7c93 100755 --- a/ci/release/build.sh +++ b/ci/release/build.sh @@ -7,7 +7,7 @@ help() { cat </d2-.tar.gz +$0 builds D2 release archives into ./ci/release/build//d2---.tar.gz The version is detected via git describe which will use the git tag for the current commit if available. @@ -32,12 +32,13 @@ Flags: --run=regex Use to run only the OS-ARCH jobs that match the given regex. e.g. --run=linux only runs the linux jobs. --run=linux-amd64 only runs the linux-amd64 job. + +--version vX.X.X + Use to overwrite the version detected from git. EOF } main() { - VERSION="$(git_describe_ref)" - BUILD_DIR="ci/release/build/$VERSION" while :; do flag_parse "$@" case "$FLAG" in @@ -64,6 +65,11 @@ main() { host-only) flag_noarg && shift "$FLAGSHIFT" HOST_ONLY=1 + LOCAL=1 + ;; + version) + flag_nonemptyarg && shift "$FLAGSHIFT" + VERSION=$FLAGARG ;; '') shift "$FLAGSHIFT" @@ -79,6 +85,8 @@ main() { flag_errusage "no arguments are accepted" fi + VERSION=${VERSION:-$(git_describe_ref)} + BUILD_DIR=ci/release/build/$VERSION if [ -n "${HOST_ONLY-}" ]; then runjob $(os)-$(arch) "OS=$(os) ARCH=$(arch) build" & waitjobs @@ -93,8 +101,8 @@ main() { } build() { - HW_BUILD_DIR="$BUILD_DIR/$OS/$ARCH/d2-$VERSION" - ARCHIVE="$BUILD_DIR/d2-$OS-$ARCH-$VERSION.tar.gz" + HW_BUILD_DIR="$BUILD_DIR/$OS-$ARCH/d2-$VERSION" + ARCHIVE="$BUILD_DIR/d2-$VERSION-$OS-$ARCH.tar.gz" if [ -e "$ARCHIVE" -a -z "${REBUILD-}" ]; then log "skipping as already built at $ARCHIVE" diff --git a/ci/release/gen_install.sh b/ci/release/gen_install.sh index fd49041d4..def56ac2f 100755 --- a/ci/release/gen_install.sh +++ b/ci/release/gen_install.sh @@ -30,6 +30,7 @@ sh_c cat \ ./ci/sub/lib/rand.sh \ ./ci/sub/lib/log.sh \ ./ci/sub/lib/flag.sh \ + ./ci/sub/lib/release.sh \ \| sed "-e'/^\. /d'" \>\> ./install.sh sh_c cat ./ci/release/_install.sh \ \| sed -n "'/cd -- \"\$(dirname/,/cd -/!p'" \>\> install.sh diff --git a/ci/release/release.sh b/ci/release/release.sh index 56bb2c023..45850cd50 100755 --- a/ci/release/release.sh +++ b/ci/release/release.sh @@ -21,6 +21,8 @@ Flags: changelogs/v0.0.99-alpha.1.md. This is because you want to maintain the changelog entries for the eventual final release. --dry-run: Print the commands that would be ran without executing them. +--skip-build: Skip the build in case you want to upload your own specific assets. + Mainly for testing and debugging. Process: @@ -82,6 +84,10 @@ main() { flag_noarg && shift "$FLAGSHIFT" DRY_RUN=1 ;; + skip-build) + flag_noarg && shift "$FLAGSHIFT" + SKIP_BUILD=1 + ;; '') shift "$FLAGSHIFT" break @@ -185,15 +191,19 @@ _7_ensure_pr() { return 0 fi - pr_url="$(sh_c gh pr create --fill --body "$body" | tee /dev/stderr)" + pr_url="$(sh_c gh pr create --fill --body "'$body'" | tee /dev/stderr)" } _8_ensure_assets() { + if [ "${SKIP_BUILD-}" ]; then + warn "skipping building of assets due to --skip-build" + return 0 + fi sh_c ./ci/release/build.sh ${REBUILD:+--rebuild} } _9_upload_assets() { - sh_c gh release upload --clobber "$VERSION" "./ci/release/build/$VERSION"/*.tar.gz + ./ci/release/upload_assets.sh $VERSION } main "$@" diff --git a/ci/release/template/Makefile b/ci/release/template/Makefile index a93267ed7..5b9ba1353 100644 --- a/ci/release/template/Makefile +++ b/ci/release/template/Makefile @@ -5,8 +5,8 @@ PREFIX = $(DESTDIR)/usr/local .PHONY: install install: - ./scripts/install.sh + PREFIX='$(PREFIX)' ./scripts/install.sh .PHONY: uninstall uninstall: - ./scripts/uninstall.sh + PREFIX='$(PREFIX)' ./scripts/uninstall.sh diff --git a/ci/release/upload_assets.sh b/ci/release/upload_assets.sh new file mode 100755 index 000000000..f14da46b6 --- /dev/null +++ b/ci/release/upload_assets.sh @@ -0,0 +1,47 @@ +#!/bin/sh +set -eu +cd -- "$(dirname "$0")/../.." +. ./ci/sub/lib.sh + +help() { + cat < + +Uploads the assets for release to GitHub. + +For example, if is v0.0.99 then it uploads files matching +./ci/release/build/v0.0.99/*.tar.gz to the GitHub release v0.0.99. + +Example: + $0 v0.0.99 +EOF +} + +main() { + while :; do + flag_parse "$@" + case "$FLAG" in + h|help) + help + return 0 + ;; + '') + shift "$FLAGSHIFT" + break + ;; + *) + flag_errusage "unrecognized flag $FLAGRAW" + ;; + esac + done + + if [ $# -ne 1 ]; then + flag_errusage "first argument must be release version like v0.0.99" + fi + VERSION="$1" + shift + + sh_c gh release upload --clobber "$VERSION" "./ci/release/build/$VERSION"/*.tar.gz +} + +main "$@" diff --git a/ci/sub b/ci/sub index 81e033b77..5a1c8e5e3 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 81e033b7702131e917a16396b44c20512d29029b +Subproject commit 5a1c8e5e36a0b0c4b0d5e2ad4e08c3c815dd4bea diff --git a/install.sh b/install.sh index 8c8a11f2a..061999567 100755 --- a/install.sh +++ b/install.sh @@ -499,6 +499,13 @@ main() { if [ $# -gt 0 ]; then flag_errusage "no arguments are accepted" fi + + REPO=${REPO:-terrastruct/d2} + latest_version +} + +latest_version() { + curl -fsSLI -o/dev/null -w '%{url_effective}' "https://github.com/$REPO/latest" } main "$@" diff --git a/lib/version/version.go b/lib/version/version.go index ef7703a06..65db5ca1c 100644 --- a/lib/version/version.go +++ b/lib/version/version.go @@ -2,6 +2,7 @@ package version import ( "context" + "fmt" "github.com/google/go-github/github" "oss.terrastruct.com/cmdlog" @@ -11,12 +12,17 @@ import ( var Version = "master (built from source)" func CheckVersion(ctx context.Context, logger *cmdlog.Logger) { - logger.Info.Printf("D2 version: %s\n", Version) + fmt.Println(Version) if Version == "master (built from source)" { return } + // Install script uses -v to check the version, we shouldn't be checking for + // updates here... + // https://github.com/terrastruct/d2/issues/49#issuecomment-1313229683 + return + logger.Info.Printf("Checking for updates...") latest, err := getLatestVersion(ctx) if err != nil {