From 06e60c22895deb57e1ce50e625ac4f3056832e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lovro=20Ma=C5=BEgon?= Date: Mon, 4 Nov 2024 13:32:03 +0100 Subject: [PATCH] license, github actions, linter config, gitignore --- .github/CODEOWNERS | 1 + .github/dependabot.yml | 19 ++ .../workflows/dependabot-auto-merge-go.yml | 39 ++++ .github/workflows/lint.yml | 20 ++ .github/workflows/project-automation.yml | 11 + .github/workflows/test.yml | 20 ++ .../workflows/validate-generated-files.yml | 33 +++ .gitignore | 23 ++ .golangci.goheader.template | 13 ++ .golangci.yml | 124 +++++++++++ LICENSE.md | 201 ++++++++++++++++++ decorators.go | 4 +- ecdysis_test.go | 8 +- 13 files changed, 512 insertions(+), 4 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/dependabot-auto-merge-go.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/project-automation.yml create mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/validate-generated-files.yml create mode 100644 .gitignore create mode 100644 .golangci.goheader.template create mode 100644 .golangci.yml create mode 100644 LICENSE.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..2a28730 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @ConduitIO/conduit-core diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9b777ec --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +# Docs: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: ".github:" + + # Maintain dependencies for Go + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: "go.mod:" diff --git a/.github/workflows/dependabot-auto-merge-go.yml b/.github/workflows/dependabot-auto-merge-go.yml new file mode 100644 index 0000000..a8ea26a --- /dev/null +++ b/.github/workflows/dependabot-auto-merge-go.yml @@ -0,0 +1,39 @@ +# This action automatically merges dependabot PRs that update go dependencies (only patch and minor updates). +# Based on: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/automating-dependabot-with-github-actions#enable-auto-merge-on-a-pull-request + +name: Dependabot auto-merge +on: + pull_request: + # Run this action when dependabot labels the PR, we care about the 'go' label. + types: [labeled] + +permissions: + pull-requests: write + contents: write + +jobs: + dependabot-go: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' && contains(github.event.pull_request.labels.*.name, 'go') }} + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2.2.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Approve PR + # Approve only patch and minor updates + if: ${{ steps.metadata.outputs.update-type != 'version-update:semver-major' }} + run: gh pr review --approve "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Enable auto-merge for Dependabot PRs + # Enable auto-merging only for patch and minor updates + if: ${{ steps.metadata.outputs.update-type != 'version-update:semver-major' }} + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..d201a4d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,20 @@ +name: lint + +on: + push: + branches: [ main ] + pull_request: + +jobs: + golangci-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: "v1.61.0" diff --git a/.github/workflows/project-automation.yml b/.github/workflows/project-automation.yml new file mode 100644 index 0000000..b6f7d54 --- /dev/null +++ b/.github/workflows/project-automation.yml @@ -0,0 +1,11 @@ +name: project-management + +on: + issues: + types: [opened] + +jobs: + project-mgmt: + uses: ConduitIO/automation/.github/workflows/project-automation.yml@main + secrets: + project-automation-token: ${{ secrets.PROJECT_AUTOMATION }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..0bc1e6b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,20 @@ +name: test + +on: + push: + branches: [ main ] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: Test + run: go test -race -v ./... \ No newline at end of file diff --git a/.github/workflows/validate-generated-files.yml b/.github/workflows/validate-generated-files.yml new file mode 100644 index 0000000..ce4436f --- /dev/null +++ b/.github/workflows/validate-generated-files.yml @@ -0,0 +1,33 @@ +name: validate-generated-files + +on: + push: + branches: [ main ] + pull_request: + +jobs: + validate-generated-files: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + # This step sets up the variable steps.mockgen-version.outputs.v + # to contain the version of mockgen (e.g. v0.5.0). + # The version is taken from go.mod. + - name: Mockgen version + id: mockgen-version + run: | + MOCKGEN_VERSION=$( go list -m -f '{{.Version}}' go.uber.org/mock ) + echo "v=$MOCKGEN_VERSION" >> "$GITHUB_OUTPUT" + + - name: Check generated files + env: + BUF_TOKEN: ${{ secrets.BUF_TOKEN }} + run: | + export PATH=$PATH:$(go env GOPATH)/bin + go install go.uber.org/mock/mockgen@${{ steps.mockgen-version.outputs.v }} + go generate ./... + git diff --exit-code --numstat diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fcd01fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +/vendor + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +### Intellij ### +.idea + +### VisualStudioCode ### +.vscode + +### macOS ### +.DS_Store diff --git a/.golangci.goheader.template b/.golangci.goheader.template new file mode 100644 index 0000000..947c941 --- /dev/null +++ b/.golangci.goheader.template @@ -0,0 +1,13 @@ +Copyright © {{ copyright-year }} Meroxa, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..f39c51c --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,124 @@ +run: + timeout: 5m + +linters-settings: + nolintlint: + allow-unused: false # report any unused nolint directives + require-explanation: true # require an explanation for nolint directives + require-specific: true # require nolint directives to mention the specific linter being suppressed + goconst: + ignore-tests: true + goheader: + template-path: '.golangci.goheader.template' + values: + regexp: + copyright-year: 20[2-9]\d + wrapcheck: + ignoreSigs: + - .Errorf( + - errors.New( + - errors.Unwrap( + - errors.Join( + - .Wrap( + - .Wrapf( + - .WithMessage( + - .WithMessagef( + - .WithStack( + - (context.Context).Err() + +issues: + exclude-rules: + - path: _test\.go + linters: + - dogsled + - gosec + - gocognit + - errcheck + - forcetypeassert + - funlen + - dupl + - maintidx + +linters: + # please, do not use `enable-all`: it's deprecated and will be removed soon. + # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - copyloopvar + - decorder + # - depguard + - dogsled + - dupl + - dupword + - durationcheck + # - err113 + - errcheck + - errchkjson + - errname + - errorlint + - exhaustive + # - forbidigo + - forcetypeassert + - funlen + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecknoinits + - gocognit + - goconst + - gocritic + - godot + - gofmt + - gofumpt + - goheader + - goimports + - gomoddirectives + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + # - ireturn # Doesn't have correct support for generic types https://github.com/butuzov/ireturn/issues/37 + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - musttag + - nakedret + - nestif + - nilerr + - nilnil + - noctx + - nolintlint + - nosprintfhostport + - prealloc + - predeclared + - promlinter + - reassign + - revive + - rowserrcheck + - sqlclosecheck + - staticcheck + - stylecheck + - tenv + - testableexamples + - thelper + - unconvert + # - unparam + - unused + - usestdlibvars + - wastedassign + - whitespace + - wrapcheck + - zerologlint diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..9d1be85 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright © 2024 Meroxa, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/decorators.go b/decorators.go index f5cbb77..90f44c3 100644 --- a/decorators.go +++ b/decorators.go @@ -115,7 +115,7 @@ type CommandWithFlagsDecorator struct{} // Decorate sets the command flags. // -//nolint:funlen,gocyclo // this function has a big switch statement, can't get around that +//nolint:funlen,gocyclo,gocognit,forcetypeassert // this function has a big switch statement, can't get around that func (CommandWithFlagsDecorator) Decorate(_ *Ecdysis, cmd *cobra.Command, c Command) error { v, ok := c.(CommandWithFlags) if !ok { @@ -463,7 +463,7 @@ func (CommandWithConfirmDecorator) Decorate(_ *Ecdysis, cmd *cobra.Command, c Co fmt.Printf("To proceed, type %q or re-run this command with --force\n▸ ", wantInput) input, err := reader.ReadString('\n') if err != nil { - return err + return fmt.Errorf("failed to read user input: %w", err) } if wantInput != strings.TrimRight(input, "\r\n") { diff --git a/ecdysis_test.go b/ecdysis_test.go index e64cc38..119af42 100644 --- a/ecdysis_test.go +++ b/ecdysis_test.go @@ -43,9 +43,11 @@ var ( func (c *testCmd) Usage() string { return "cmd1" } + func (c *testCmd) Aliases() []string { return []string{"foo", "bar"} } + func (c *testCmd) Docs() Docs { return Docs{ Short: "short-foo", @@ -53,11 +55,13 @@ func (c *testCmd) Docs() Docs { Example: "example-baz", } } + func (c *testCmd) Flags() []Flag { return []Flag{ {Long: "long-foo", Short: "l", Usage: "test flag", Required: false, Persistent: false, Ptr: &c.flagLongFoo}, } } + func (c *testCmd) SubCommands(e *Ecdysis) []*cobra.Command { return []*cobra.Command{ e.MustBuildCobraCommand(&subCmd{}), @@ -93,7 +97,7 @@ func TestBuildCobraCommand_Structural(t *testing.T) { got.PostRunE = nil if v := cmp.Diff(got, want, cmpopts.IgnoreUnexported(cobra.Command{})); v != "" { - t.Fatalf(v) + t.Fatal(v) } } @@ -214,6 +218,6 @@ func TestBuildCommandWithFlags(t *testing.T) { got.PostRunE = nil if v := cmp.Diff(got, want, cmpopts.IgnoreUnexported(cobra.Command{})); v != "" { - t.Fatalf(v) + t.Fatal(v) } }