From e8713aaabbca2aa461b99cdcb26b1399af1b6ae8 Mon Sep 17 00:00:00 2001 From: Dan Brakeley Date: Sat, 22 Jun 2024 14:44:05 -0400 Subject: [PATCH] automate release builds * switch to new ansi package so I don't depend on frog and go-isatty * clean up magefile * add reinstall-mage bash script --- .github/workflows/release.yaml | 24 +++++++++++++ .github/workflows/test.yaml | 20 +++++++++++ .vscode/launch.json | 17 ++++++++++ README.md | 20 +++++++++-- aws/README.md | 4 +-- cmd/upmyip/main.go | 24 ++++++++++++- cmd/upmyip/print.go | 2 +- cmd/upmyip/spinner.go | 2 +- go.mod | 6 ++-- go.sum | 17 ++-------- internal/buildvar/buildvar.go | 10 ++++++ magefile.go | 62 +++++++++++++++++++++++++++------- scripts/reinstall-mage.sh | 21 ++++++++++++ 13 files changed, 189 insertions(+), 40 deletions(-) create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/test.yaml create mode 100644 .vscode/launch.json create mode 100644 internal/buildvar/buildvar.go create mode 100644 scripts/reinstall-mage.sh diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..103ef0c --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,24 @@ +name: build release zip + +on: + release: + types: [created] + +jobs: + release: + name: Release Go Binary + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: wangyoucao577/go-release-action@v1.51 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + goos: windows + goarch: amd64 + goversion: "go.mod" + project_path: "./cmd/upmyip" + ldflags: + '-X "github.com/danbrakeley/upmyip/internal/buildvar.Version=${{ github.event.release.tag_name }}" + -X "github.com/danbrakeley/upmyip/internal/buildvar.BuildTime=${{ github.event.release.created_at + }}" -X "github.com/danbrakeley/upmyip/internal/buildvar.ReleaseURL=${{ + github.event.release.html_url }}"' diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..8b6697b --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,20 @@ +name: validate commit +on: [pull_request] +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - + uses: actions/checkout@v4 + - + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - + uses: magefile/mage-action@v3 + with: + version: latest + args: ci diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..dbac5f6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Build & Debug", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/upmyip", + "output": "local", + "cwd": "local", + } + ] +} diff --git a/README.md b/README.md index a484a8f..7cfdde9 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,27 @@ If you find something wrong/broken, please let me know and/or open a PR to help - Install a recent version of [Go](https://go.dev/dl/) - Install [Mage](https://magefile.org/) -- run `mage` to see the build targets + - There's a helper bash script for installing and upgrading Mage here: `./scripts/reinstall-mage.sh`. +- run `mage` to see the build targets, e.g. + ```text + $ mage + Targets: + all tests, builds, and packages all targets + ci runs all CI tasks + lambda tests, builds, and packages the lambda + lambdaBuild builds the lamda (output goes to "local" folder) + lambdaZip zips the lambda + test tests all packages + upMyIP tests and builds the upmyip cli app + upMyIPBuild builds the upmyip cli app + upMyIPRun runs the upmyip cli app in the "local" folder + ``` -Note that building and packaging happen in the `local` folder (which is ignored by git). +Building and packaging happen in the `local` folder, which is ignored by git. ### Building the Lambda -- run `mage buildlambda` +- run `mage lambda` - output is `local/lambda.zip` Note that deploying code changes to all running lambdas can be automated via some bash script in [aws/README.md](aws/README.md). diff --git a/aws/README.md b/aws/README.md index a0ec206..475f4a4 100644 --- a/aws/README.md +++ b/aws/README.md @@ -21,7 +21,7 @@ ``` 3. Build and upload lambda function ```text - $ mage buildlambda + $ mage lambda Running unit tests... Building lambda... Zipping executable to local/lambda.zip... @@ -54,7 +54,7 @@ aws lambda invoke --function-name FUNCITON_NAME_OR_ARN --payload '{"ip":"10.0.0. 1. Build and upload lambda function ```text - $ mage buildlambda + $ mage lambda Running unit tests... Building lambda... Zipping executable to local/lambda.zip... diff --git a/cmd/upmyip/main.go b/cmd/upmyip/main.go index 3f27f9d..602664c 100644 --- a/cmd/upmyip/main.go +++ b/cmd/upmyip/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "errors" "fmt" "os" @@ -9,15 +10,36 @@ import ( "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/danbrakeley/upmyip/internal/buildvar" ) func main() { + var showVersionAndQuit bool + if len(os.Args) > 1 { + if os.Args[1] == "-v" || os.Args[1] == "--version" || os.Args[1] == "version" { + showVersionAndQuit = true + } + } + _, noColor := os.LookupEnv("NO_COLOR") prn := Printer{ NoColor: noColor, } - prn.Header("UpMyIP v0.1.2") + prn.Header("UpMyIP " + buildvar.Version) + + if showVersionAndQuit { + prn.Print("Build Time: ") + prn.BrightPrintln(buildvar.BuildTime) + prn.Print("Release URL: ") + prn.BrightPrintln(buildvar.ReleaseURL) + return + } + + if len(os.Args) > 1 { + prn.Error("unexpected argument", errors.New(os.Args[1])) + return + } cfg, err := LoadConfig("upmyip.toml") if err != nil { diff --git a/cmd/upmyip/print.go b/cmd/upmyip/print.go index 020de09..0739827 100644 --- a/cmd/upmyip/print.go +++ b/cmd/upmyip/print.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/danbrakeley/frog/ansi" + "github.com/danbrakeley/ansi" ) type Printer struct { diff --git a/cmd/upmyip/spinner.go b/cmd/upmyip/spinner.go index 0f57e3a..f9887c6 100644 --- a/cmd/upmyip/spinner.go +++ b/cmd/upmyip/spinner.go @@ -5,7 +5,7 @@ import ( "sync" "time" - "github.com/danbrakeley/frog/ansi" + "github.com/danbrakeley/ansi" ) type Spinner struct { diff --git a/go.mod b/go.mod index 2ea1ca6..091197b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/danbrakeley/upmyip -go 1.22.3 +go 1.22 require ( github.com/BurntSushi/toml v1.4.0 @@ -10,8 +10,8 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.17.18 github.com/aws/aws-sdk-go-v2/service/ec2 v1.164.1 github.com/aws/aws-sdk-go-v2/service/lambda v1.54.6 + github.com/danbrakeley/ansi v0.1.0 github.com/danbrakeley/bsh v0.2.0 - github.com/danbrakeley/frog v0.10.0 github.com/magefile/mage v1.15.0 ) @@ -29,6 +29,4 @@ require ( github.com/aws/smithy-go v1.20.2 // indirect github.com/danbrakeley/commandline v1.0.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - golang.org/x/sys v0.5.0 // indirect ) diff --git a/go.sum b/go.sum index 039faa7..7b93b9b 100644 --- a/go.sum +++ b/go.sum @@ -34,12 +34,12 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/danbrakeley/ansi v0.1.0 h1:E6LmV05pp2z4hSY6yV+T1SPGKl5rHt7KitPdreLX0JU= +github.com/danbrakeley/ansi v0.1.0/go.mod h1:UgVuevQbNorh1SDBSWuw8jmG+QURBskDDqJ31YG6BGQ= github.com/danbrakeley/bsh v0.2.0 h1:ymKekjFekftmn2eEQvQk0MDjuhdaiTVLeI6mEfy52us= github.com/danbrakeley/bsh v0.2.0/go.mod h1:s6MsY0JONwbMmO6PucUyqTSULGTPTTdRMohD0iccFtA= github.com/danbrakeley/commandline v1.0.0 h1:9qOX7wnJxECT0ZEZav6P5/GVdX/xSsPnIwQ9ptpMUuc= github.com/danbrakeley/commandline v1.0.0/go.mod h1:TebcfPCZN3Dpc0DZMp68KTbVzCr07KCfAVkrYlLi2is= -github.com/danbrakeley/frog v0.10.0 h1:YtORqrv+3J0w/1t7GKl/I3+cDfI2xhEFKDRC5ARCYJM= -github.com/danbrakeley/frog v0.10.0/go.mod h1:p2AWOH3knZHylnQLcDqoR633mOi6UMpFVPzV9iTNPUg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -50,24 +50,11 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/buildvar/buildvar.go b/internal/buildvar/buildvar.go new file mode 100644 index 0000000..690bec1 --- /dev/null +++ b/internal/buildvar/buildvar.go @@ -0,0 +1,10 @@ +package buildvar + +// -ldflags '-X "github.com/danbrakeley/upmyip/internal/buildvar.Version=${{ github.event.release.tag_name }}"' +var Version string + +// -ldflags '-X "github.com/danbrakeley/upmyip/internal/buildvar.BuildTime=${{ github.event.release.created_at }}"' +var BuildTime string + +// -ldflags '-X "github.com/danbrakeley/upmyip/internal/buildvar.ReleaseURL=${{ github.event.release.html_url }}"' +var ReleaseURL string diff --git a/magefile.go b/magefile.go index 797ec2b..76768d2 100644 --- a/magefile.go +++ b/magefile.go @@ -3,48 +3,84 @@ package main import ( + "bytes" + "strings" + "time" + "github.com/danbrakeley/bsh" "github.com/magefile/mage/mg" ) var sh = &bsh.Bsh{} +// Test tests all packages func Test() { sh.Echo("Running unit tests...") sh.Cmd("go test ./...").Run() } -// BuildLambda tests and builds the lamda (output goes to "local" folder) -func BuildLambda() { - mg.SerialDeps(Test) - +// LambdaBuild builds the lamda (output goes to "local" folder) +func LambdaBuild() { sh.MkdirAll("local/") sh.Echof("Building lambda...") sh.Cmd( "go build -o local/bootstrap -tags lambda.norpc ./cmd/lambda/", ).Env("GOOS=linux", "GOARCH=arm64", "CGO_ENABLED=0").Run() +} +// LambdaZip zips the lambda +func LambdaZip() { sh.Echof("Zipping executable to local/lambda.zip...") sh.ZipFile("local/bootstrap", "local/lambda.zip") } -func Build() { - mg.SerialDeps(Test) +// Lambda tests, builds, and packages the lambda +func Lambda() { + mg.SerialDeps(Test, LambdaBuild, LambdaZip) +} +// UpMyIPBuild builds the upmyip cli app +func UpMyIPBuild() { + exeName := sh.ExeName("upmyip") + sh.Echof("Building local/%s...", exeName) sh.MkdirAll("local/") + // grab git commit hash to use as version for local builds + commit := "(dev)" + var b bytes.Buffer + n := sh.Cmd(`git log --pretty=format:'%h' -n 1`).Out(&b).Err(&b).RunExitStatus() + if n == 0 { + commit = strings.TrimSpace(b.String()) + } + + sh.Cmdf( + `go build -ldflags '`+ + `-X "github.com/danbrakeley/upmyip/internal/buildvar.Version=%s" `+ + `-X "github.com/danbrakeley/upmyip/internal/buildvar.BuildTime=%s" `+ + `-X "github.com/danbrakeley/upmyip/internal/buildvar.ReleaseURL=https://github.com/danbrakeley/upmyip"`+ + `' -o local/%s ./cmd/upmyip/`, commit, time.Now().Format(time.RFC3339), exeName, + ).Run() +} + +// UpMyIPRun runs the upmyip cli app in the "local" folder +func UpMyIPRun() { exeName := sh.ExeName("upmyip") - sh.Echof("Building local/%s...", exeName) - sh.Cmdf("go build -o local/%s ./cmd/upmyip/", exeName).Run() + sh.Echo("Running...") + sh.Cmdf("./%s", exeName).Dir("local").Run() } -// Run runs unit tests, builds, and runs the app +// UpMyIP tests and builds the upmyip cli app func UpMyIP() { - mg.SerialDeps(Test, Build) + mg.SerialDeps(Test, UpMyIPBuild) +} - exeName := sh.ExeName("upmyip") +// All tests, builds, and packages all targets +func All() { + mg.SerialDeps(Test, Lambda, UpMyIPBuild) +} - sh.Echo("Running...") - sh.Cmdf("./%s", exeName).Dir("local").Run() +// CI runs all CI tasks +func CI() { + mg.SerialDeps(Test, LambdaBuild, UpMyIPBuild) } diff --git a/scripts/reinstall-mage.sh b/scripts/reinstall-mage.sh new file mode 100644 index 0000000..08ea560 --- /dev/null +++ b/scripts/reinstall-mage.sh @@ -0,0 +1,21 @@ +#!/bin/bash -e +cd $(dirname "$0") + +TMPFOLDER=$(mktemp -d) || exit 1 +trap 'rm -rf "$TMPFOLDER"' EXIT + +if command -v mage &> /dev/null +then + echo "--- MAGE VERSION BEFORE" + mage -version + echo "---" +fi + +cd $TMPFOLDER +git clone https://github.com/magefile/mage +cd mage +go run bootstrap.go + +echo "--- MAGE VERSION" +mage -version +echo "---"