diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..086c049 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,15 @@ +# [Choice] https://github.com/KEINOS/VSCode-Dev-Container-Go/pkgs/container/vscode-dev-container-go +ARG VARIANT="latest" + +# ----------------------------------------------------------------------------- +# Main Stage +# ----------------------------------------------------------------------------- +FROM ghcr.io/keinos/vscode-dev-container-go:${VARIANT} + +# [Optional] Uncomment this section to install additional OS packages. +# USER root +# RUN apk add --no-cache + +# [Optional] Uncomment this section to go install anything else you need. +# USER vscode +# RUN cd /tmp && go install "@" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..8965666 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,46 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.191.1/containers/go +{ + "name": "Go Dev", + "build": { + "dockerfile": "Dockerfile", + "args": { + // Choices: https://github.com/KEINOS/VSCode-Dev-Container-Go/pkgs/container/vscode-dev-container-go + "VARIANT": "latest" + } + }, + "runArgs": [ + "--rm", + "--cap-add=SYS_PTRACE", + "--security-opt", + "seccomp=unconfined" + ], + + // Set *default* container specific settings.json values on container create. + "settings": { + "go.toolsManagement.checkForUpdates": "local", + "go.useLanguageServer": true, + "go.gopath": "/go", + "go.goroot": "/usr/local/go", + "terminal.integrated.profiles.linux": { + "bash (login)": { + "path": "/bin/bash", + "args": [] + } + } + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "golang.Go" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "go mod download", + + // Comment out to connect as root to debug container. + // "remoteUser": "root" +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..40ac025 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,33 @@ +# ----------------------------------------------------------------------------- +# Editor settings +# ----------------------------------------------------------------------------- + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.go] +indent_style = tab + +# Shell-format +[*.sh] +indent_style = space # shfmt -i=4 +indent_size = 4 # shfmt -i=4 +shell_variant = posix # shfmt -ln=posix +binary_next_line = false # disable shfmt -bn +switch_case_indent = true # shfmt -ci +space_redirects = false # disable shfmt -sr +keep_padding = true # shfmt -kp +function_next_line = false # disable shfmt -fn + +[*.{yml,yaml,json}] +indent_style = space +indent_size = 4 +insert_final_newline = false +quote_type = single \ No newline at end of file diff --git a/.github/Dockerfile b/.github/Dockerfile new file mode 100644 index 0000000..1443b9a --- /dev/null +++ b/.github/Dockerfile @@ -0,0 +1,19 @@ +# ============================================================================= +# Test Container for Vaious Go Versions +# ============================================================================= +# Default version +ARG VARIANT="1.14-alpine" + +# ----------------------------------------------------------------------------- +# Main Stage +# ----------------------------------------------------------------------------- +FROM golang:${VARIANT} + +RUN apk add --no-cache \ + git \ + alpine-sdk \ + build-base + +WORKDIR /workspaces + +ENTRYPOINT go mod download && go test -race ./... diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..a0e4da9 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,24 @@ +# Security Policy + +## Supported Go Versions + +We run the tests every week scheduled with the below Go versions. + +| Version | Supported | +| :------ | :----------------: | +| 1.14.15+ | :white_check_mark: | +| 1.15.15+ | :white_check_mark: | +| 1.16.8+ | :white_check_mark: | +| 1.17.1+ | :white_check_mark: | + +## Code Scaning + +[![CodeQL](https://github.com/KEINOS/dev-go/actions/workflows/codeQL-analysis.yml/badge.svg)](https://github.com/KEINOS/dev-go/actions/workflows/codeQL-analysis.yml) + +## Security Status + +- Check the current "[Security overview](https://github.com/KEINOS/dev-go/security)" status. + +## Reporting a Vulnerability + +- Please [issue](https://github.com/KEINOS/dev-go/issues) them. \ No newline at end of file diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml new file mode 100644 index 0000000..7d8faec --- /dev/null +++ b/.github/docker-compose.yml @@ -0,0 +1,72 @@ +# ============================================================================= +# Docker Compose file for testing on Go versions 1.14~1.17 and latest. +# ============================================================================= +# It is recommended to run specifying a specific Go version and not at once. +# +# Since the service `tidy` will update/re-write the "go.mod" file to the latest +# version, during it's process the "go.mod" file will be gone temporarily. Thus, +# it will cause failure in the other container becaue of missing "go.mod" file. +# +# Recommended usage: +# docker-compose --file ./.github/docker-compose.yml run tidy && \ +# docker-compose --file ./.github/docker-compose.yml run 1.14 +# +# NOT recommended to run all tests at once whith "up": +# docker-compose --file ./.github/docker-compose.yml up +version: "3.9" +services: + # Service tidy updates the go.mod to the latest + tidy: + build: + context: .. + dockerfile: ./.github/Dockerfile + args: + VARIANT: 1.14-alpine + volumes: + - ..:/workspaces + entrypoint: [ "./.github/go-mod-tidy.sh" ] + # Service v1_14 runs the tests on Go v1.14 + v1_14: + build: + context: .. + dockerfile: ./.github/Dockerfile + args: + VARIANT: 1.14-alpine + volumes: + - ..:/workspaces + # Service v1_14 runs the tests on Go v1.15 + v1_15: + build: + context: .. + dockerfile: ./.github/Dockerfile + args: + VARIANT: 1.15-alpine + volumes: + - ..:/workspaces + # Service v1_14 runs the tests on Go v1.15 + v1_16: + build: + context: .. + dockerfile: ./.github/Dockerfile + args: + VARIANT: 1.16-alpine + volumes: + - ..:/workspaces + # Service v1_14 runs the tests on Go v1.16 + v1_17: + build: + context: .. + dockerfile: ./.github/Dockerfile + args: + VARIANT: 1.17-alpine + volumes: + - ..:/workspaces + # Service v1_14 runs the tests on latest Go docker image + latest: + build: + context: .. + dockerfile: ./.github/Dockerfile + args: + VARIANT: alpine + volumes: + - ..:/workspaces diff --git a/.github/go-mod-tidy.sh b/.github/go-mod-tidy.sh new file mode 100755 index 0000000..a1da480 --- /dev/null +++ b/.github/go-mod-tidy.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# ============================================================================= +# This script updates Go modules to the latest version. +# ============================================================================= +# It will remove the go.mod file and run `go mod tidy` to get the latest moule +# versions. +# Then it will run the tests to make sure the code is still working, and fails +# if any errors are found during the process. +# +# NOTE: This script is aimed to run in the container via docker-compose. +# See "tidy" service: ./docker-compose.yml +# ============================================================================= + +set -eu + +echo '* Backup modules ...' +mv go.mod go.mod.bak +mv go.sum go.sum.bak + +echo '* Create new blank go.mod ...' +< go.mod.bak head -n 4 > go.mod + +echo '* Run go tidy ...' +go mod tidy + +echo '* Run tests ...' +go test ./... && { + echo '* Testing passed. Removing old go.mod file ...' + rm -f go.mod.bak + rm -f go.sum.bak + echo 'Successfully updated modules!' +} diff --git a/.github/mergify.yml b/.github/mergify.yml new file mode 100644 index 0000000..67e00c9 --- /dev/null +++ b/.github/mergify.yml @@ -0,0 +1,20 @@ +pull_request_rules: + - name: Automatic merge on approval + conditions: + - author=KEINOS + - base=main + - title~=^Changes + - files=go.mod + - files=go.sum + - "#files=2" + - check-success=Analyze (go) + - check-success=build + - check-success=Unit test (ubuntu-latest) + - check-success=Unit test (macos-latest) + - check-success=Unit test (windows-latest) + - check-success=CodeQL + - check-success=codecov/patch + - check-success=codecov/project + actions: + merge: + method: merge \ No newline at end of file diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml new file mode 100644 index 0000000..b3d3e60 --- /dev/null +++ b/.github/workflows/code-coverage.yml @@ -0,0 +1,29 @@ +# This workflow updates the code coverage of Codecov. +# It runs the unit test and pushes the measured code coverage analysis. +name: "Codecov" + +on: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + schedule: + # Runs at 16:40 UTC on day-of-month 1 (Every day-of-month 1 at AM 01:40 JST, my time) + # See: https://crontab.guru/ + - cron: '40 16 1 * *' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 2 + - uses: actions/setup-go@v2 + with: + go-version: '1.14' + - name: Run coverage + run: go test -coverprofile=coverage.out -covermode=atomic ./... + - name: Upload coverage to Codecov + run: bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/codeQL-analysis.yml b/.github/workflows/codeQL-analysis.yml new file mode 100644 index 0000000..0d709a3 --- /dev/null +++ b/.github/workflows/codeQL-analysis.yml @@ -0,0 +1,68 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + schedule: + # Runs at 16:30 UTC on day-of-month 1 (Every day-of-month 1 at AM 01:30 JST, my time) + # See: https://crontab.guru/ + - cron: '30 16 1 * *' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml new file mode 100644 index 0000000..04ecc3c --- /dev/null +++ b/.github/workflows/go-test.yml @@ -0,0 +1,41 @@ +# This workflow runs the unit test (`go test ./...`) on vaious platforms, +# such as: Linux, macOS and Windows. +name: UnitTests + +on: + workflow_dispatch: + pull_request: + +jobs: + coverage: + name: Unit test + + strategy: + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-go@v2 + with: + go-version: '^1.17' + + - name: Use Cache + uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Download Modules + if: steps.cache.outputs.cache-hit != 'true' + run: go mod download + + - name: Run unit test + run: | + go mod download + go test -race -v ./... diff --git a/.github/workflows/go-versions.yml b/.github/workflows/go-versions.yml new file mode 100644 index 0000000..6ac69fa --- /dev/null +++ b/.github/workflows/go-versions.yml @@ -0,0 +1,84 @@ +name: go1.14+ + +on: + workflow_dispatch: + push: + branches: [ main ] + schedule: + # Runs at 16:05 UTC on day-of-month 1 (Every day-of-month 1 at AM 01:05 JST, my time) + # See: https://crontab.guru/ + - cron: '5 16 1 * *' + +env: + PATH_CACHE: /tmp/docker-img-arch + +jobs: + go: + name: Run tests on Go via container + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Create image tag + id: imagetag + run: | + HASH_IMAGE=${{ hashFiles('./.github/Dockerfile') }} + VARIANT=$(TZ=UTC-9 date '+%Y%m') + TAG="${HASH_IMAGE:0:7}:${VARIANT}" + PATH_TAR=${{ env.PATH_CACHE }}"/tar" + echo "::set-output name=TAG::${TAG}" + echo "::set-output name=PATH_TAR::${PATH_TAR}" + + - name: Cache or restore image archive + id: cache + uses: actions/cache@v2 + with: + path: ${{ env.PATH_CACHE }} + key: ${{ steps.imagetag.outputs.TAG }} + + - name: Load Docker images if exist + if: steps.cache.outputs.cache-hit == 'true' + run: | + docker load --input ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_14_1.tar + docker load --input ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_15_1.tar + docker load --input ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_16_1.tar + docker load --input ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_17_1.tar + docker load --input ${{ steps.imagetag.outputs.PATH_TAR }}/github_latest_1.tar + + - name: Pull base images if no-exist + if: steps.cache.outputs.cache-hit != 'true' + run: | + : # Pull images one-by-one for stability + docker pull golang:1.14-alpine + docker pull golang:1.15-alpine + docker pull golang:1.16-alpine + docker pull golang:1.17-alpine + docker pull golang:alpine + + - name: Build Docker images if no-exists + if: steps.cache.outputs.cache-hit != 'true' + run: | + mkdir -p ${{ steps.imagetag.outputs.PATH_TAR }} + : # Build container images + docker-compose --file ./.github/docker-compose.yml build + + - name: Save built images if no-exists + if: steps.cache.outputs.cache-hit != 'true' + run: | + docker save --output ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_14_1.tar github_v1_14:latest + docker save --output ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_15_1.tar github_v1_15:latest + docker save --output ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_16_1.tar github_v1_16:latest + docker save --output ${{ steps.imagetag.outputs.PATH_TAR }}/github_v1_17_1.tar github_v1_17:latest + docker save --output ${{ steps.imagetag.outputs.PATH_TAR }}/github_latest_1.tar github_latest:latest + + - name: Run tests on Go 1.14 + run: docker-compose --file ./.github/docker-compose.yml run v1_14 + - name: Run tests on Go 1.15 + run: docker-compose --file ./.github/docker-compose.yml run v1_15 + - name: Run tests on Go 1.16 + run: docker-compose --file ./.github/docker-compose.yml run v1_16 + - name: Run tests on Go 1.17 + run: docker-compose --file ./.github/docker-compose.yml run v1_17 + - name: Run tests on latest Go + run: docker-compose --file ./.github/docker-compose.yml run latest diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000..6f0b56e --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,30 @@ +# Details of this action see: https://github.com/golangci/golangci-lint-action +name: golangci-lint + +on: + workflow_dispatch: + push: + branches: [ main ] + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest + + # Optional: working directory, useful for monorepos + # working-directory: somedir + + # Optional: golangci-lint command line arguments. + args: --config ./.golangci.yml + + # Optional: show only new issues if it's a pull request. The default value is `false`. + # only-new-issues: true + + # Optional: if set to true then the action will use pre-installed Go + # skip-go-installation: true diff --git a/.github/workflows/release_bin.yml b/.github/workflows/release_bin.yml new file mode 100644 index 0000000..41abb88 --- /dev/null +++ b/.github/workflows/release_bin.yml @@ -0,0 +1,34 @@ +# ============================================================================= +# Release Assets and Homebrew's Tap +# ============================================================================= +# This workflow will build the binaries and push the archives to the assets in +# the releases page if a release was created. Then pushes the tap config file +# for Homebrew tap. See: ../../.goreleaser.yml +name: Release + +on: + workflow_dispatch: + release: + types: + - created + tags: + - 'v*' +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: '1.17.x' + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + version: latest + args: release --config .goreleaser.yml + env: + GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/weekly-update.yml b/.github/workflows/weekly-update.yml new file mode 100644 index 0000000..d185569 --- /dev/null +++ b/.github/workflows/weekly-update.yml @@ -0,0 +1,49 @@ +# ============================================================================= +# Weekly Module Update +# ============================================================================= +# This workflow runs weekly to update and test the latest `go.mod` version. +# +# If all the tests succeeds to run in all Go versions, it will create a new PR +# of the `go.mod` and `go.sum`. +# +# NOTE: +# You need to set the `PERSONAL_ACCESS_TOKEN` environment variable in the repo's +# [Settings]-[Secrets]-[Actions secrets] +# To generate a new token go to: +# https://github.com/settings/tokens +# * You need add the "repo" scope to the token but no more. +# ============================================================================= +name: Weekly Update + +on: + workflow_dispatch: + schedule: + # Runs at 18:00 UTC on Sun (JST: AM 03:00 on every Monday) + - cron: '0 18 * * SUN' + +jobs: + automated_build: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Update go.mod and run tests + run: | + set -eu + docker-compose --file ./.github/docker-compose.yml run tidy && \ + docker-compose --file ./.github/docker-compose.yml run v1_14 && \ + docker-compose --file ./.github/docker-compose.yml run v1_15 && \ + docker-compose --file ./.github/docker-compose.yml run v1_16 && \ + docker-compose --file ./.github/docker-compose.yml run v1_17 && \ + docker-compose --file ./.github/docker-compose.yml run latest + + - name: Create Pull Request on Change + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..22fdbf0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Ignore distribution/binary release directory +dist/ +bin/ diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..6a68e4e --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,237 @@ +# This file contains configuration options for GolangCI-Lint. +# - Available linters see: https://golangci-lint.run/usage/linters/ +# - Sample of config see: https://golangci-lint.run/usage/configuration/#config-file + +# options for analysis running +run: + # include test files or not, default is true + tests: true + + fast: true + + # list of build tags, all linters use it. Default is empty list. + build-tags: + - golangci + + # which dirs to skip: issues from them won't be reported; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but default dirs are skipped independently + # from this option's value (see skip-dirs-use-default). + # "/" will be replaced by current OS file path separator to properly work + # on Windows. + skip-dirs: + - .devcontainer + - .github + - .vscode + - bin + + # Allow multiple parallel golangci-lint instances running. + # If false (default) - golangci-lint acquires file lock on start. + allow-parallel-runners: true + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" + format: colored-line-number + + # sorts results by: filepath, line and column + sort-results: true + +# enabled linters. Conf settings follows. +linters: + enable: + - deadcode # Finds unused code + - dogsled + - dupl + - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - funlen + - gocognit + - gocritic + - gocyclo + - godot + - godox + - gofmt + - gofumpt # Stricter gofmt + #- golint # Deprecated. Use revive + - gosec # Inspects source code for security problems + - gosimple # Linter for Go source code that specializes in simplifying a code + - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - ifshort + - ineffassign # Detects when assignments to existing variables are not used + - lll + - megacheck # gosimple, staticcheck, unused + - misspell # Find commonly misspelled English words in comments + - nakedret # Limit naked returns in functions greater than a specified function length + - nestif # Limit if statements nested deep + - nolintlint # Don't allow 'nolint' annotation w/out a description + - nlreturn # Requires a new line before return + - prealloc # Finds slice declarations that could potentially be preallocated + - predeclared # Find code that shadows one of Go's predeclared identifiers + - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint + - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks + - structcheck # Finds unused struct fields + - stylecheck + - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code + - unconvert # Detect unnecessary type conversions + - unused # Checks Go code for unused constants, variables, functions and types + #- testpackage # Limit use unexported functions and methods from source code in tests + - thelper # Enforce to call 't.Helper()' in the test helper function + - varcheck # Finds unused global variables and constants + - whitespace # Limit unnecessary newlines at the start and end of functions, if, for, etc + - wsl # Enforce empty lines at the right places to make code more readable. + +# settings of linters +linters-settings: + dogsled: + # checks assignments with too many blank identifiers; default is 2 + max-blank-identifiers: 2 + dupl: + # tokens count to trigger issue, 150 by default + threshold: 100 + errcheck: + # report about not checking of errors in type assertions: `a := b.(MyStruct)`; + # default is false: such cases aren't reported by default. + check-type-assertions: true + funlen: + lines: 60 + statements: 40 + gocognit: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + gocritic: + # Which checks should be enabled; can't be combined with 'disabled-checks'; + # See https://go-critic.github.io/overview#checks-overview + # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` + # By default list of stable checks is used. + enabled-checks: + - rangeValCopy + - hugeParam + # The settings key is the name of a supported gocritic checker. + # The list of supported checkers can be find in https://go-critic.github.io/overview. + settings: + hugeParam: + # size in bytes that makes the warning trigger (default 80) + sizeThreshold: 70 + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + godot: + # check that each sentence starts with a capital letter + capital: true + godox: + # report any comments starting with keywords, this is useful for TODO or FIXME comments that + # might be left in the code accidentally and should be resolved before merging + keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting + - TODO + - BUG + - FIXME + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + gofumpt: + # Choose whether or not to use the extra rules that are disabled + # by default + extra-rules: false + golint: + # minimal confidence for issues, default is 0.8 + min-confidence: 0.95 + govet: + enable-all: true + ifshort: + # Maximum length of variable declaration measured in number of lines, after which linter won't suggest using short syntax. + # Has higher priority than max-decl-chars. + max-decl-lines: 1 + # Maximum length of variable declaration measured in number of characters, after which linter won't suggest using short syntax. + max-decl-chars: 30 + lll: + # max line length, lines longer will be reported. Default is 120. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option + line-length: 120 + # tab width in spaces. Default to 1. + tab-width: 1 + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: US + nakedret: + # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 + max-func-lines: 25 + nestif: + # minimal complexity of if statements to report, 5 by default + min-complexity: 4 + nolintlint: + # Enable to ensure that nolint directives are all used. Default is true. + allow-unused: false + # Disable to ensure that nolint directives don't have a leading space. Default is true. + allow-leading-space: false + # Enable to require an explanation of nonzero length after each nolint directive. Default is false. + require-explanation: true + # Enable to require nolint directives to mention the specific linter being suppressed. Default is false. + require-specific: true + unused: + # treat code as a program (not a library) and report unused exported identifiers; default is false. + # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find funcs usages. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + check-exported: false + revive: + # see https://github.com/mgechev/revive#available-rules for details. + ignore-generated-header: true + severity: warning + rules: + - name: indent-error-flow + severity: warning + testpackage: + # regexp pattern to skip files. ***_internal_test.go and ***_export_test.go are the exception. + skip-regexp: (export|internal)_test\.go + thelper: + # The following configurations enable all checks. It can be omitted because all checks are enabled by default. + # You can enable only required checks deleting unnecessary checks. + test: + first: true + name: true + begin: true + benchmark: + first: true + name: true + begin: true + whitespace: + multi-if: false # Enforces newlines (or comments) after every multi-line if statement + multi-func: false # Enforces newlines (or comments) after every multi-line function signature + wsl: + # If true append is only allowed to be cuddled if appending value is + # matching variables, fields or types on line above. Default is true. + strict-append: true + # Allow calls and assignments to be cuddled as long as the lines have any + # matching variables, fields or types. Default is true. + allow-assign-and-call: true + # Allow multiline assignments to be cuddled. Default is true. + allow-multiline-assign: true + # Allow declarations (var) to be cuddled. + allow-cuddle-declarations: false + # Allow trailing comments in ending of blocks + allow-trailing-comment: false + # Force newlines in end of case at this limit (0 = never). + force-case-trailing-whitespace: 0 + # Force cuddling of err checks with err var assignment + force-err-cuddling: false + # Allow leading comments to be separated with empty liens + allow-separated-leading-comment: false + errorlint: + # Report non-wrapping error creation using fmt.Errorf + errorf: true + makezero: + # Allow only slices initialized with a length of zero. Default is false. + always: false + forbidigo: + # Forbid the following identifiers + forbid: + - fmt.Errorf # consider errors.Errorf in github.com/pkg/errors + - fmt.Print.* # too much log noise + - ginkgo\\.F.* # these are used just for local development + # Exclude godoc examples from forbidigo checks. Default is true. + exclude_godoc_examples: false \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..2654fa2 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,109 @@ +# ============================================================================= +# Configuration for `goreleaser`. +# ============================================================================= +# For local-test run: +# $ goreleaser release --snapshot --skip-publish --rm-dist +# $ # *Note: Check the ./bin/ dir after ran. +# +# Make sure to check the documentation as well at: +# https://goreleaser.com/customization/ +# ============================================================================= +before: + hooks: + - go mod download +# Name to use on test release with --snapshot option. +snapshot: + name_template: '{{ .Version }}' + +# Directory name to distribute +dist: bin + +# Settings to build the binaries. +builds: + - + # Target directory of main.go package + main: ./cmd/whereami + # Output binary name + binary: whereami + env: + - CGO_ENABLED=0 + # Target OS + goos: + - linux + - windows + - darwin + # Target architectures + goarch: + - amd64 + - arm + - arm64 + # Variant for ARM32 + goarm: + - "5" + - "6" + - "7" + # Ignore ARM32/ARM64 build for both macOS and Windows + ignore: + - goos: darwin + goarch: arm + - goos: windows + goarch: arm + - goos: windows + goarch: arm64 + # Build the app as static binary and embed version and commit info + ldflags: + - -s -w -extldflags '-static' -X 'main.version={{.Version}}' -X 'main.commit={{ .ShortCommit }}' + +# macOS universal binaries for both arm64 and amd64 +universal_binaries: + - + name_template: 'whereami' + # Combine arm64 and amd64 as a single binary and remove each + replace: true + +# Archiving the built binaries +archives: + - + replacements: + darwin: macOS + linux: Linux + windows: Windows + amd64: x86_64 + format_overrides: + - goos: windows + format: zip + - goos: darwin + format: zip + +# Create checksum file of archived files +checksum: + name_template: 'checksums.txt' + +# Release/update Homebrew tap repository +brews: + - + # Name of the Homebrew package: //Formula/.rb + name: whereami + # Target repo to tap: KEINOS/homebrew-apps + tap: + owner: KEINOS + name: homebrew-apps + # Target directory: KEINOS/homebrew-apps/Formula + folder: Formula + # URL of the archive in releases page + url_template: "https://github.com/KEINOS/whereami/releases/download/{{ .Tag }}/{{ .ArtifactName }}" + # Author info to commit to the tap repo + commit_author: + name: goreleaserbot + email: goreleaser@carlosbecker.com + # Message to display on `brew search` or `brew info` + description: "This is a command line utility that prints the current global/public IP address." + homepage: "https://github.com/KEINOS/whereami/" + # Let brew command pull the archive via cURL + download_strategy: CurlDownloadStrategy + # Let brew command instll the binary as `whereami` + install: | + bin.install "whereami" + # Smoke test to run after install + test: | + system "#{bin}/whereami --version" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2b0e796 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 KEINOS and the WhoAmI contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3031bf8 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# WhereAmI + +`whereami` is a command line utility that prints the current global/public IP address. + +```bash +$ whereami +123.13.14.253 +``` + +## Install + +- Via [Homebrew](https://brew.sh/) for macOS, Linux and Windows WSL2. (Intel,AMD64/ARM64,M1) + + ```bash + brew install KEINOS/apps/whereami + ``` + +- For manual download or other architectures see [releases page](/). diff --git a/cmd/whereami/main.go b/cmd/whereami/main.go new file mode 100644 index 0000000..ceae512 --- /dev/null +++ b/cmd/whereami/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + + "github.com/KEINOS/go-utiles/util" +) + +func main() { + util.ExitOnErr(Run()) +} + +// Run is the actual function of the app. +func Run() error { + fmt.Println("Hello, Gopher!") + + return nil +} diff --git a/cmd/whereami/main_test.go b/cmd/whereami/main_test.go new file mode 100644 index 0000000..ebf76fb --- /dev/null +++ b/cmd/whereami/main_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/zenizh/go-capturer" +) + +func Test_main(t *testing.T) { + out := capturer.CaptureStdout(func() { + main() + }) + + assert.Equal(t, out, "Hello, Gopher!\n") +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0391bd5 --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module github.com/KEINOS/dev-go + +go 1.14 + +require ( + github.com/KEINOS/go-utiles v1.5.3 + github.com/stretchr/testify v1.7.0 + github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ff3e443 --- /dev/null +++ b/go.sum @@ -0,0 +1,56 @@ +github.com/KEINOS/go-utiles v1.5.3 h1:IIo5qacRuR5adSfmojPKYjZjAaxw4I4Vv4iphsueOxM= +github.com/KEINOS/go-utiles v1.5.3/go.mod h1:kDM/EQVRa4w+JNWiBcJFqELacpHT+5uVxnx327Drh38= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +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= +github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= +github.com/jedib0t/go-pretty/v6 v6.2.4 h1:wdaj2KHD2W+mz8JgJ/Q6L/T5dB7kyqEFI16eLq7GEmk= +github.com/jedib0t/go-pretty/v6 v6.2.4/go.mod h1:+nE9fyyHGil+PuISTCrp7avEdo6bqoMwqZnuiK2r2a0= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d h1:cVtBfNW5XTHiKQe7jDaDBSh/EVM4XLPutLAGboIXuM0= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w= +github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04/go.mod h1:FiwNQxz6hGoNFBC4nIx+CxZhI3nne5RmIOlT/MXcSD4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= +lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=