Skip to content

Commit

Permalink
Merge pull request #186 from WillAbides/bootsy
Browse files Browse the repository at this point in the history
bootstrap command
  • Loading branch information
WillAbides authored Nov 24, 2023
2 parents c2a9b44 + 32d5fd7 commit 49874b1
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 102 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,5 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
script/bindown -q install gh
go run ./internal/build-bootstrapper -tag "$RELEASE_TAG" > bootstrap-bindown.sh
script/bindown bootstrap --tag "$RELEASE_TAG" --output bootstrap-bindown.sh
bin/gh release upload "$RELEASE_TAG" bootstrap-bindown.sh
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ Commands:
checksums
init create an empty config file
cache clear clear the cache
bootstrap create bootstrap script for bindown
version show bindown version
install-completions install shell completions
Expand Down
51 changes: 51 additions & 0 deletions cmd/bindown/bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

import (
"fmt"
"os"
"path/filepath"
"strings"

bootstrapper "github.com/willabides/bindown/v4/internal/build-bootstrapper"
)

func defaultBootstrapTag() string {
if Version == "unknown" {
return ""
}
return "v" + Version
}

type bootstrapCmd struct {
Tag string `kong:"hidden,default=${bootstrap_tag_default}"`
BaseURL string `kong:"hidden,name='base-url',default='https://github.com'"`
Output string `kong:"help='output file, writes to stdout if not set',type='path'"`
}

func (c *bootstrapCmd) Run(ctx *runContext) error {
if c.Tag == "" {
return fmt.Errorf("version is required")
}
tag := c.Tag
if !strings.HasPrefix(tag, "v") {
tag = "v" + tag
}
opts := bootstrapper.BuildOpts{BaseURL: c.BaseURL}
content, err := bootstrapper.Build(tag, &opts)
if err != nil {
return err
}
if c.Output == "" {
fmt.Fprint(ctx.stdout, content)
return nil
}
err = os.MkdirAll(filepath.Dir(c.Output), 0o755)
if err != nil {
return err
}
err = os.WriteFile(c.Output, []byte(content), 0o755)
if err != nil {
return err
}
return nil
}
29 changes: 29 additions & 0 deletions cmd/bindown/bootstrap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
"github.com/willabides/bindown/v4/internal/testutil"
)

func Test_bootstrapCmd(t *testing.T) {
output := filepath.Join(t.TempDir(), "foo", "bootstrap.sh")
runner := newCmdRunner(t)

server := testutil.ServeFile(
t,
testdataPath("build-bootstrapper/checksums.txt"),
"/WillAbides/bindown/releases/download/v4.8.0/checksums.txt",
"",
)
want, err := os.ReadFile(testdataPath("build-bootstrapper/bootstrap-bindown.sh"))
require.NoError(t, err)
result := runner.run("bootstrap", "--output", output, "--tag", "4.8.0", "--base-url", server.URL)
result.assertState(resultState{})
got, err := os.ReadFile(output)
require.NoError(t, err)
require.Equal(t, string(want), string(got))
}
2 changes: 2 additions & 0 deletions cmd/bindown/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var kongVars = kong.Vars{
"install_to_cache_help": `install to cache instead of install dir`,
"install_wrapper_help": `install a wrapper script instead of the binary`,
"install_bindown_help": `path to bindown executable to use in wrapper`,
"bootstrap_tag_default": defaultBootstrapTag(),
}

type rootCmd struct {
Expand All @@ -59,6 +60,7 @@ type rootCmd struct {
Checksums checksumsCmd `kong:"cmd,help='manage checksums'"`
Init initCmd `kong:"cmd,help='create an empty config file'"`
Cache cacheCmd `kong:"cmd,help='manage the cache'"`
Bootstrap bootstrapCmd `kong:"cmd,help='create bootstrap script for bindown'"`

Version versionCmd `kong:"cmd,help='show bindown version'"`
InstallCompletions kongplete.InstallCompletions `kong:"cmd,help=${config_install_completions_help}"`
Expand Down
1 change: 1 addition & 0 deletions docs/clihelp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Commands:
checksums
init create an empty config file
cache clear clear the cache
bootstrap create bootstrap script for bindown
version show bindown version
install-completions install shell completions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@

set -e

TAG="v3.15.5"
TAG="v4.8.0"

CHECKSUMS="
00e936e28e816ac4f05e3f9e47aad3771df3a847fcbea3f3bbe33159508b478d bindown_3.15.5_darwin_arm64
07568b436622d3a28cbd4e9a81c6b619e4e3d9533e8f65184f0e9cf3f82df620 bindown_3.15.5_linux_arm64.tar.gz
0c06832f8a795e99dfebe550482cf790c9a7cca304635a8393dfba0eb7c1c872 bindown_3.15.5_windows_arm64.tar.gz
1727fb1a696e46432ac6110f73524e5ae87d0a136e2c649049e3886db9260331 bindown_3.15.5_windows_amd64.exe
25a9b2bf3e7ae99935cd7d93034a5166192120d9e8a572f4b38a124baa62e274 bindown_3.15.5_windows_arm64.exe
43c099b123585df691a0018ebd63def5c2876f64fe6fe2e736792e359ac489b9 bindown_3.15.5_linux_amd64
59266496ab2410582726d11bb8204cc11ba69e0333d9d6b016f912d19ab30885 bindown_3.15.5_darwin_amd64
6334cf81db488a4ac217c1799d165a6a96dd74a76cc08e080487fbb32d15fdf6 bindown_3.15.5_linux_amd64.tar.gz
72cdb65fb8361c0bc9cb85fd7768e75cb831f3527365ae348e62bba9ca44d6c6 bindown_3.15.5_linux_arm64
87d9f9b81010e83ca16115634503071673f3d898e073326524e795e50b37e690 bindown_3.15.5_windows_386.exe
90a6d0fb9fd59004aa80dc0738773b59e4d4c3ed7428996695583c1eee5cc18b bindown_3.15.5_windows_386.tar.gz
b1099c0f3558ccc70a06d5c33b2172b3cc911a13b58388e7d6573c7ca01471be bindown_3.15.5_windows_amd64.tar.gz
c4a5f4f80c5729bf56b9448798ae3aebb61104bf7bb46f6b04adaf0c650cd4e2 bindown_3.15.5_darwin_amd64.tar.gz
cdb3c98fa5bee90e6c5c3e3e8f2214513f1a7bad1ade2663180ac1cce3ef0701 bindown_3.15.5_darwin_arm64.tar.gz
d3b824e6b1bab234ac76a00e5d073fca647e917efd05df3fe620e9771a74d037 bindown_3.15.5_linux_386.tar.gz
e2a62bfb094bd973d9e215f520effbab236ef7acdc9b5d592be688f624a30454 bindown_3.15.5_linux_386
26fcbc738bf9bb910b070f236816b2dfe5bc9589be3a578135f37d950ebaf771 bindown_4.8.0_freebsd_amd64.tar.gz
2fa6460ebe8d7c6be33576acf5b63f7208780af72d758e82313f6c5772e097d5 bindown_4.8.0_linux_386.tar.gz
32e3fbfaecf41a1b2bced22c1842b3905f4e6de1e879a4db68402799c206415d bindown_4.8.0_windows_386.exe
335802ed91fa6f040e10570479a6c817c7e42bd57fe98c959890a821099d3e1f bindown_4.8.0_freebsd_arm64
372846f7edd9d93df0cb17889790f595f17cb083e093f3e6437d34e3253fd378 bindown_4.8.0_windows_amd64.exe
40acf94b7c69e5d4101cb46ea99641d302ff23579cd7ead29a5abfceb1a5d9ba bindown_4.8.0_linux_arm64.tar.gz
66aca230d9aea549ecd3647082b63752f5bb5307ef6954a08cc0eaf9c70723f1 bindown_4.8.0_windows_amd64.tar.gz
752c78a926be1287312eea3c831e841e223de4780d1e4a8a813432d0a73f890b bindown_4.8.0_linux_amd64.tar.gz
7f1f1c883beceb6ec3919484511fb20c3ceb41088e814d6fc234b015e98b78d9 bindown_4.8.0_darwin_arm64
7fdfbc007c0c285a498bf251bd4ab7469f334752581b45fda5ad6450ddd23377 bindown_4.8.0_windows_arm64.exe
95764bf76b54d5b13b9b8a801635d82447ee349c3545145ddd8a0a84246d66e2 bindown_4.8.0_freebsd_arm64.tar.gz
966087f13a6cf82804456119289ab982f2eee3ad04d8d4fb6ce74bd7eabdf74e bindown_4.8.0_windows_386.tar.gz
9b29e37ba273bc0dca9c8227ee4b58153289073ede7d900e9c84ae3c71f3dff5 bindown_4.8.0_windows_arm64.tar.gz
a625900e52f4413bee3863062463cc24f9c0669841fd6bc9979ee599edd88f3e bindown_4.8.0_freebsd_amd64
ba09df557edc4499f41ddadc26369d7f70ed20bfb8310662f1290e6a355343e8 bindown_4.8.0_darwin_amd64.tar.gz
cd7b917d2737fe9fa087aea172d9b581757e9b300fa1d1dbd83c1b765be05bdb bindown_4.8.0_freebsd_386.tar.gz
d5d35274d4eab337c107940fc5b326c51f5bfd70d00924c79011684e2a0d4f22 bindown_4.8.0_freebsd_386
d71d6c436ad33bb3aa01468698b86d5423127a19f9b1c664e346cc502501d415 bindown_4.8.0_darwin_arm64.tar.gz
d9361698bc1571c34915496da9c624e89fa12d87731711efd2cbbc9136c6fa85 bindown_4.8.0_darwin_amd64
d93eae8638b96682d0e9b55bcbe92fecb296afd442e0526cc94ce0160c108c13 bindown_4.8.0_linux_arm64
ec3d19abd00fbf099a98edb64c569842fa5b909222fb10da86d668f5597885be bindown_4.8.0_linux_amd64
fa7e87f49aa30e42485431bd9dd021a32924ab11e4d39065533e9bccce182de4 bindown_4.8.0_linux_386
"

cat /dev/null << EOF
Expand Down Expand Up @@ -242,8 +248,6 @@ usage() {
this=$1
cat << EOT
Usage: $this [-b bindir] [-d]
Usage: $this [-b] bindir [-d]
-b sets bindir or installation directory, Defaults to ./bin
-d turns on debug logging
Expand All @@ -267,6 +271,14 @@ parse_args() {
shift $((OPTIND - 1))
}

bindown_name() {
if [ "$OS" = "windows" ]; then
echo bindown.exe
else
echo bindown
fi
}

execute() {
tmpdir=$(mktemp -d)
echo "$CHECKSUMS" > "${tmpdir}/checksums.txt"
Expand All @@ -276,15 +288,17 @@ execute() {
srcdir="${tmpdir}"
(cd "${tmpdir}" && untar "${TARBALL}")
test ! -d "${BINDIR}" && install -d "${BINDIR}"
binexe="bindown"
if [ "$OS" = "windows" ]; then
binexe="${binexe}.exe"
fi
install "${srcdir}/${binexe}" "${BINDIR}/"
log_info "installed ${BINDIR}/${binexe}"
install "${srcdir}/$(bindown_name)" "${BINDIR}/"
log_info "installed ${BINDIR}/$(bindown_name)"
rm -rf "${tmpdir}"
}

already_installed() {
VERSION="$1"
[ -f "${BINDIR}/$(bindown_name)" ] &&
"${BINDIR}/$(bindown_name)" version 2> /dev/null | grep -q "$VERSION"
}

OS=$(uname_os)
ARCH=$(uname_arch)

Expand All @@ -294,6 +308,12 @@ uname_arch_check "$ARCH"
parse_args "$@"

VERSION=${TAG#v}

if already_installed "$VERSION"; then
log_debug "bindown ${VERSION} is already installed"
exit 0
fi

NAME=bindown_${VERSION}_${OS}_${ARCH}
TARBALL=${NAME}.${FORMAT}
TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
Expand Down
22 changes: 22 additions & 0 deletions internal/bindown/testdata/build-bootstrapper/checksums.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
26fcbc738bf9bb910b070f236816b2dfe5bc9589be3a578135f37d950ebaf771 bindown_4.8.0_freebsd_amd64.tar.gz
2fa6460ebe8d7c6be33576acf5b63f7208780af72d758e82313f6c5772e097d5 bindown_4.8.0_linux_386.tar.gz
32e3fbfaecf41a1b2bced22c1842b3905f4e6de1e879a4db68402799c206415d bindown_4.8.0_windows_386.exe
335802ed91fa6f040e10570479a6c817c7e42bd57fe98c959890a821099d3e1f bindown_4.8.0_freebsd_arm64
372846f7edd9d93df0cb17889790f595f17cb083e093f3e6437d34e3253fd378 bindown_4.8.0_windows_amd64.exe
40acf94b7c69e5d4101cb46ea99641d302ff23579cd7ead29a5abfceb1a5d9ba bindown_4.8.0_linux_arm64.tar.gz
66aca230d9aea549ecd3647082b63752f5bb5307ef6954a08cc0eaf9c70723f1 bindown_4.8.0_windows_amd64.tar.gz
752c78a926be1287312eea3c831e841e223de4780d1e4a8a813432d0a73f890b bindown_4.8.0_linux_amd64.tar.gz
7f1f1c883beceb6ec3919484511fb20c3ceb41088e814d6fc234b015e98b78d9 bindown_4.8.0_darwin_arm64
7fdfbc007c0c285a498bf251bd4ab7469f334752581b45fda5ad6450ddd23377 bindown_4.8.0_windows_arm64.exe
95764bf76b54d5b13b9b8a801635d82447ee349c3545145ddd8a0a84246d66e2 bindown_4.8.0_freebsd_arm64.tar.gz
966087f13a6cf82804456119289ab982f2eee3ad04d8d4fb6ce74bd7eabdf74e bindown_4.8.0_windows_386.tar.gz
9b29e37ba273bc0dca9c8227ee4b58153289073ede7d900e9c84ae3c71f3dff5 bindown_4.8.0_windows_arm64.tar.gz
a625900e52f4413bee3863062463cc24f9c0669841fd6bc9979ee599edd88f3e bindown_4.8.0_freebsd_amd64
ba09df557edc4499f41ddadc26369d7f70ed20bfb8310662f1290e6a355343e8 bindown_4.8.0_darwin_amd64.tar.gz
cd7b917d2737fe9fa087aea172d9b581757e9b300fa1d1dbd83c1b765be05bdb bindown_4.8.0_freebsd_386.tar.gz
d5d35274d4eab337c107940fc5b326c51f5bfd70d00924c79011684e2a0d4f22 bindown_4.8.0_freebsd_386
d71d6c436ad33bb3aa01468698b86d5423127a19f9b1c664e346cc502501d415 bindown_4.8.0_darwin_arm64.tar.gz
d9361698bc1571c34915496da9c624e89fa12d87731711efd2cbbc9136c6fa85 bindown_4.8.0_darwin_amd64
d93eae8638b96682d0e9b55bcbe92fecb296afd442e0526cc94ce0160c108c13 bindown_4.8.0_linux_arm64
ec3d19abd00fbf099a98edb64c569842fa5b909222fb10da86d668f5597885be bindown_4.8.0_linux_amd64
fa7e87f49aa30e42485431bd9dd021a32924ab11e4d39065533e9bccce182de4 bindown_4.8.0_linux_386
76 changes: 34 additions & 42 deletions internal/build-bootstrapper/build.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
package main
package bootstrapper

import (
"bytes"
"embed"
"flag"
"errors"
"fmt"
"io"
"net/http"
"os/exec"
"path/filepath"
"runtime"
"strings"
"text/template"
)

//go:embed assets/*
var assets embed.FS

func build(tag, repoRoot string) (_ string, errOut error) {
bindownCmd := exec.Command("script/bindown", "install", "shfmt", "shellcheck")
bindownCmd.Dir = repoRoot
err := bindownCmd.Run()
if err != nil {
return "", err
type BuildOpts struct {
BaseURL string // defaults to https://github.com
}

// Build builds a bootstrapper for the given tag
func Build(tag string, opts *BuildOpts) (_ string, errOut error) {
if opts == nil {
opts = &BuildOpts{}
}
baseURL := opts.BaseURL
if baseURL == "" {
baseURL = "https://github.com"
}
checksumsURL := fmt.Sprintf(
`https://github.com/WillAbides/bindown/releases/download/%s/checksums.txt`,
tag,
`%s/WillAbides/bindown/releases/download/%s/checksums.txt`,
baseURL, tag,
)
resp, err := http.Get(checksumsURL)
if err != nil {
return "", err
}
defer func() {
err = resp.Body.Close()
if errOut == nil {
errOut = err
}
}()
defer func() { errOut = errors.Join(errOut, resp.Body.Close()) }()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("got status %d from %s", resp.StatusCode, checksumsURL)
}
Expand Down Expand Up @@ -70,32 +70,24 @@ func build(tag, repoRoot string) (_ string, errOut error) {
if err != nil {
return "", err
}
shfmtCmd := exec.Command(filepath.Join(repoRoot, "bin", "shfmt"), "-i", "2", "-ci", "-sr", "-")
shfmtCmd.Stdin = &tmplOut
formatted, err := shfmtCmd.Output()
if err != nil {
return "", err
out := strings.TrimSpace(tmplOut.String()) + "\n"
if runtime.GOOS == "windows" {
out = windowsLineEndings(out)
}
shellcheckCmd := exec.Command(filepath.Join(repoRoot, "bin", "shellcheck"), "--shell", "sh", "-")
shellcheckCmd.Stdin = bytes.NewReader(formatted)
err = shellcheckCmd.Run()
if err != nil {
return "", err
}
return string(formatted), nil
return out, nil
}

func main() {
var tag, repoRoot string
flag.StringVar(&tag, "tag", "", "tag to build")
flag.StringVar(&repoRoot, "repo-root", ".", "path to bindown repo root")
flag.Parse()
if tag == "" {
panic("tag is required")
}
got, err := build(tag, repoRoot)
if err != nil {
panic(err)
func windowsLineEndings(in string) string {
buf := bytes.NewBuffer(make([]byte, 0, len(in)))
for i := 0; i < len(in); i++ {
if in[i] != '\n' {
buf.WriteByte(in[i])
continue
}
if i == 0 || in[i-1] != '\r' {
buf.WriteByte('\r')
}
buf.WriteByte('\n')
}
fmt.Println(got)
return buf.String()
}
33 changes: 0 additions & 33 deletions internal/build-bootstrapper/build_test.go

This file was deleted.

Loading

0 comments on commit 49874b1

Please sign in to comment.