From 079d5244a0ae9e187ed9067cec2c90bfed324e2e Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 13 Sep 2022 22:58:43 -0700 Subject: [PATCH 1/5] Convert project to Go module This will allow the use of modern Go dependency management and project management capabilities. --- go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b48e0fc --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/arduino/arduinoOTA + +go 1.17 From 27020ddaaff1803e5e221bfa3fe5e452e786bf42 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 13 Sep 2022 23:03:32 -0700 Subject: [PATCH 2/5] Add CI workflow to lint and check formatting of Go code On every push and pull request that affects relevant files, check the Go module for: - Common detectable errors in the code. - Use of outdated APIs - Code style violations - Code formatting inconsistency - Misconfiguration --- .github/workflows/check-go-task.yml | 223 ++++++++++++++++++++++++++++ README.md | 1 + Taskfile.yml | 41 +++++ 3 files changed, 265 insertions(+) create mode 100644 .github/workflows/check-go-task.yml diff --git a/.github/workflows/check-go-task.yml b/.github/workflows/check-go-task.yml new file mode 100644 index 0000000..5ea86a0 --- /dev/null +++ b/.github/workflows/check-go-task.yml @@ -0,0 +1,223 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-go-task.md +name: Check Go + +env: + # See: https://github.com/actions/setup-go/tree/main#supported-version-syntax + GO_VERSION: "1.17" + +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows +on: + create: + push: + paths: + - ".github/workflows/check-go-task.ya?ml" + - "Taskfile.ya?ml" + - "**/go.mod" + - "**/go.sum" + - "**.go" + pull_request: + paths: + - ".github/workflows/check-go-task.ya?ml" + - "Taskfile.ya?ml" + - "**/go.mod" + - "**/go.sum" + - "**.go" + schedule: + # Run periodically to catch breakage caused by external changes. + - cron: "0 7 * * WED" + workflow_dispatch: + repository_dispatch: + +jobs: + run-determination: + runs-on: ubuntu-latest + outputs: + result: ${{ steps.determination.outputs.result }} + steps: + - name: Determine if the rest of the workflow should run + id: determination + run: | + RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" + # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. + if [[ + "${{ github.event_name }}" != "create" || + "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX + ]]; then + # Run the other jobs. + RESULT="true" + else + # There is no need to run the other jobs. + RESULT="false" + fi + + echo "::set-output name=result::$RESULT" + + check-errors: + name: check-errors (${{ matrix.module.path }}) + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + module: + - path: ./ + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Check for errors + env: + GO_MODULE_PATH: ${{ matrix.module.path }} + run: task go:vet + + check-outdated: + name: check-outdated (${{ matrix.module.path }}) + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + module: + - path: ./ + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Modernize usages of outdated APIs + env: + GO_MODULE_PATH: ${{ matrix.module.path }} + run: task go:fix + + - name: Check if any fixes were needed + run: git diff --color --exit-code + + check-style: + name: check-style (${{ matrix.module.path }}) + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + module: + - path: ./ + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Install golint + run: go install golang.org/x/lint/golint@latest + + - name: Check style + env: + GO_MODULE_PATH: ${{ matrix.module.path }} + run: task --silent go:lint + + check-formatting: + name: check-formatting (${{ matrix.module.path }}) + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + module: + - path: ./ + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Format code + env: + GO_MODULE_PATH: ${{ matrix.module.path }} + run: task go:format + + - name: Check formatting + run: git diff --color --exit-code + + check-config: + name: check-config (${{ matrix.module.path }}) + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + module: + - path: ./ + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Run go mod tidy + working-directory: ${{ matrix.module.path }} + run: go mod tidy + + - name: Check whether any tidying was needed + run: git diff --color --exit-code diff --git a/README.md b/README.md index 7c94e3b..48c389e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # arduinoOTA [![Check General Formatting status](https://github.com/arduino/arduinoOTA/actions/workflows/check-general-formatting-task.yml/badge.svg)](https://github.com/arduino/arduinoOTA/actions/workflows/check-general-formatting-task.yml) +[![Check Go status](https://github.com/arduino/arduinoOTA/actions/workflows/check-go-task.yml/badge.svg)](https://github.com/arduino/arduinoOTA/actions/workflows/check-go-task.yml) [![Check npm status](https://github.com/arduino/arduinoOTA/actions/workflows/check-npm-task.yml/badge.svg)](https://github.com/arduino/arduinoOTA/actions/workflows/check-npm-task.yml) [![Check Prettier Formatting status](https://github.com/arduino/arduinoOTA/actions/workflows/check-prettier-formatting-task.yml/badge.svg)](https://github.com/arduino/arduinoOTA/actions/workflows/check-prettier-formatting-task.yml) [![Spell Check status](https://github.com/arduino/arduinoOTA/actions/workflows/spell-check-task.yml/badge.svg)](https://github.com/arduino/arduinoOTA/actions/workflows/spell-check-task.yml) diff --git a/Taskfile.yml b/Taskfile.yml index 2173c03..fd78b2b 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -2,6 +2,11 @@ version: "3" vars: + # Path of the project's primary Go module: + DEFAULT_GO_MODULE_PATH: ./ + DEFAULT_GO_PACKAGES: + sh: | + echo $(cd {{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}} && go list ./... | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"') # Last version of ajv-cli with support for the JSON schema "Draft 4" specification SCHEMA_DRAFT_4_AJV_CLI_VERSION: 3.3.0 @@ -74,6 +79,42 @@ tasks: cmds: - poetry run codespell --write-changes + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-go-task/Taskfile.yml + go:fix: + desc: Modernize usages of outdated APIs + dir: "{{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}}" + cmds: + - go fix {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-go-task/Taskfile.yml + go:format: + desc: Format Go code + dir: "{{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}}" + cmds: + - go fmt {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-go-task/Taskfile.yml + go:lint: + desc: Lint Go code + dir: "{{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}}" + cmds: + - | + if ! which golint &>/dev/null; then + echo "golint not installed or not in PATH. Please install: https://github.com/golang/lint#installation" + exit 1 + fi + - | + golint \ + {{default "-min_confidence 0.8 -set_exit_status" .GO_LINT_FLAGS}} \ + {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-go-task/Taskfile.yml + go:vet: + desc: Check for errors in Go code + dir: "{{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}}" + cmds: + - go vet {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown-task/Taskfile.yml markdown:check-links: desc: Check for broken links From cfd724a0fe65139437922450870e26f438a557bc Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 13 Sep 2022 23:16:14 -0700 Subject: [PATCH 3/5] Add doc comment for exported variable golint imposes the important requirement that all exported API components have a doc comment. From a purely technical sense, there is no reason for the developer to have exported AppVersion, since it is not used in other packages of the project and the project is exclusively a standalone application; not a reusable package. However, there is maybe a little bit of semantic sense to exporting AppVersion. The deploy.sh script uses this line of the code, so in a way it is "exported", even though it is used in an janky manner that does not care anything about Go's export framework. So the export may communicate that this line is an "API" of sorts and that modifying it must be done with care. --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 1d4f859..efce0a8 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "time" ) +// AppVersion is the application version. const AppVersion = "1.3.0" var compileInfo string From cf31ae3c947951def8968e7e193b02c8762a1d13 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 13 Sep 2022 23:33:54 -0700 Subject: [PATCH 4/5] Remove unused struct Since the developer did not bother to provide any documentation, it is not clear what purpose this thing was intended to serve. What is clear is that it does not serve any purpose now, so it must be removed. --- main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/main.go b/main.go index efce0a8..ebab63f 100644 --- a/main.go +++ b/main.go @@ -41,11 +41,6 @@ var ( timeoutSeconds = flag.Int("t", 10, "Upload timeout") ) -type Item struct { - Id int - Name string -} - func main() { flag.Parse() From d986e160ea422f97e0a6cb769b0c4d8ca4e2a7f7 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 13 Sep 2022 23:35:20 -0700 Subject: [PATCH 5/5] Do not export functions unnecessarily This project is intended only as a standalone application; not as a reusable packge. It only has a single package. For this reason, there is no reason to export functions. --- main.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index ebab63f..c716195 100644 --- a/main.go +++ b/main.go @@ -127,9 +127,9 @@ func main() { var sketchData *bytes.Buffer if *binMode { - sketchData = StreamToBytes(f) + sketchData = streamToBytes(f) } else { - str := StreamToString(f) + str := streamToString(f) re := regexp.MustCompile(`\r?\n`) str = re.ReplaceAllString(str, "") sketchData = bytes.NewBufferString(str) @@ -228,14 +228,14 @@ func main() { } } -func StreamToBytes(stream io.Reader) *bytes.Buffer { +func streamToBytes(stream io.Reader) *bytes.Buffer { buf := new(bytes.Buffer) buf.ReadFrom(stream) return buf } -func StreamToString(stream io.Reader) string { - return StreamToBytes(stream).String() +func streamToString(stream io.Reader) string { + return streamToBytes(stream).String() } func getMyIP(otherip net.IP) net.IP {