diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..17c8c10 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: CI + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.25' + + - name: golangci-lint + uses: golangci/golangci-lint-action@v9 + with: + version: v2.7.2 + args: --timeout 20m + + - name: Install deps + run: go mod download + + - name: Run fmt + run: make fmt + + - name: Run lint + run: make lint + + - name: Run tests + run: make test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7a91e52 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,75 @@ +name: Release + +on: + push: + tags: + - 'v*' + +permissions: + contents: write + +jobs: + release: + name: Build and Release + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - goos: linux + goarch: amd64 + os: ubuntu-latest + - goos: linux + goarch: arm64 + os: ubuntu-latest + - goos: windows + goarch: amd64 + os: ubuntu-latest + - goos: darwin + goarch: amd64 + os: macos-latest + - goos: darwin + goarch: arm64 + os: macos-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.25' + + - name: Import Apple Code Signing Certificates + if: matrix.goos == 'darwin' && secrets.MACOS_CERTIFICATE != '' + uses: apple-actions/import-codesign-certs@v2 + with: + p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }} + p12-password: ${{ secrets.MACOS_CERTIFICATE_PWD }} + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + CGO_ENABLED: 0 + run: | + OUTPUT_NAME=cypr-${{ matrix.goos }}-${{ matrix.goarch }} + if [ "${{ matrix.goos }}" = "windows" ]; then + OUTPUT_NAME+=".exe" + fi + + go build -v -o $OUTPUT_NAME ./cmd/main.go + + if [ "${{ matrix.goos }}" = "darwin" ] && [ -n "${{ secrets.MACOS_CERTIFICATE }}" ]; then + echo "Signing binary..." + codesign --force --options runtime --sign "$MACOS_CERTIFICATE_NAME" "$OUTPUT_NAME" + fi + env: + MACOS_CERTIFICATE_NAME: ${{ secrets.MACOS_CERTIFICATE_NAME }} + + - name: Release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + files: cypr-* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..570c775 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +.PHONY: fmt lint test + +fmt: + go fmt ./... + +lint: + # Checks if golangci-lint is installed, otherwise falls back to go vet + if command -v golangci-lint >/dev/null; then golangci-lint run; else go vet ./...; fi + +test: + go test -v ./... diff --git a/go.mod b/go.mod index 13b0e43..4cbbc9d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/blue420211/cypr -go 1.24.1 +go 1.25 require ( github.com/golang-jwt/jwt/v5 v5.2.1 diff --git a/internal/aes.go b/internal/aes.go index eda5f63..08bd685 100644 --- a/internal/aes.go +++ b/internal/aes.go @@ -64,19 +64,20 @@ func (g *AesCommand) Init(args []string) error { } func (g *AesCommand) Run() (err error) { - if g.op == "encrypt" { + switch g.op { + case "encrypt": s, err := g.encrypt(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else if g.op == "decrypt" { + case "decrypt": s, err := g.decrypt(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err diff --git a/internal/base32.go b/internal/base32.go index faedd85..ee7374c 100644 --- a/internal/base32.go +++ b/internal/base32.go @@ -47,19 +47,20 @@ func (g *Base32Command) Init(args []string) error { } func (g *Base32Command) Run() (err error) { - if g.op == "encode" { + switch g.op { + case "encode": s, err := g.encode(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else if g.op == "decode" { + case "decode": s, err := g.decode(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err diff --git a/internal/base64.go b/internal/base64.go index 1d78554..f3089d0 100644 --- a/internal/base64.go +++ b/internal/base64.go @@ -48,19 +48,20 @@ func (g *Base64Command) Init(args []string) error { } func (g *Base64Command) Run() (err error) { - if g.op == "encode" { + switch g.op { + case "encode": s, err := g.encode(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else if g.op == "decode" { + case "decode": s, err := g.decode(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err diff --git a/internal/bcrypt.go b/internal/bcrypt.go index d545e69..649566c 100644 --- a/internal/bcrypt.go +++ b/internal/bcrypt.go @@ -47,15 +47,16 @@ func (g *BcryptCommand) Init(args []string) error { return err } - if g.op == "hash" { + switch g.op { + case "hash": if g.fs.NArg() != 1 { return errors.New("invalid args, password required") } - } else if g.op == "verify" { + case "verify": if g.fs.NArg() != 2 { return errors.New("invalid args, hash and password required") } - } else { + default: return fmt.Errorf("unknown operation: %s", g.op) } @@ -64,9 +65,10 @@ func (g *BcryptCommand) Init(args []string) error { } func (g *BcryptCommand) Run() error { - if g.op == "hash" { + switch g.op { + case "hash": return g.hash(g.opArgs[0]) - } else if g.op == "verify" { + case "verify": return g.verify(g.opArgs[0], g.opArgs[1]) } return nil diff --git a/internal/hex.go b/internal/hex.go index 8e450c8..9a5e087 100644 --- a/internal/hex.go +++ b/internal/hex.go @@ -48,7 +48,8 @@ func (g *HexCommand) Init(args []string) error { } func (g *HexCommand) Run() (err error) { - if g.op == "encode" { + switch g.op { + case "encode": if g.fs.NArg() == 0 { return errors.New("data not provided") } @@ -58,13 +59,13 @@ func (g *HexCommand) Run() (err error) { return err } fmt.Println(s) - } else if g.op == "decode" { + case "decode": s, err := g.decode(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err diff --git a/internal/html.go b/internal/html.go index 65909fe..805c598 100644 --- a/internal/html.go +++ b/internal/html.go @@ -52,19 +52,20 @@ func (g *HtmlCommand) Init(args []string) error { } func (g *HtmlCommand) Run() (err error) { - if g.op == "encode" { + switch g.op { + case "encode": s, err := g.encode(g.args[0]) if err != nil { return err } fmt.Println(s) - } else if g.op == "decode" { + case "decode": s, err := g.decode(g.args[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err diff --git a/internal/jwt.go b/internal/jwt.go index a775983..165eefc 100644 --- a/internal/jwt.go +++ b/internal/jwt.go @@ -60,7 +60,8 @@ func (g *JwtCommand) Init(args []string) error { return err } - if g.op == "encode" { + switch g.op { + case "encode": if g.fs.NArg() != 3 { return errors.New("invalid args, header, payload and algo required") } @@ -69,11 +70,11 @@ func (g *JwtCommand) Init(args []string) error { return errors.New("private key and public key paths are required for RS256") } } - } else if g.op == "decode" { + case "decode": if g.fs.NArg() != 1 { return errors.New("invalid args, token required") } - } else { + default: return fmt.Errorf("unknown operation: %s", g.op) } @@ -82,19 +83,20 @@ func (g *JwtCommand) Init(args []string) error { } func (g *JwtCommand) Run() (err error) { - if g.op == "encode" { + switch g.op { + case "encode": s, err := g.encode(g.opArgs[0], g.opArgs[1], g.opArgs[2]) if err != nil { return err } fmt.Println(s) - } else if g.op == "decode" { + case "decode": s, err := g.decode(g.opArgs[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err diff --git a/internal/rand.go b/internal/rand.go index 663bb9e..4bc97ed 100644 --- a/internal/rand.go +++ b/internal/rand.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "math/rand" - "time" ) func NewRandCommand() *RandCommand { @@ -49,7 +48,6 @@ func (g *RandCommand) Run() (err error) { } func (g *RandCommand) gen() (s string, err error) { - rand.Seed(time.Now().UnixNano()) digits := "0123456789" specials := "~=+%^*/()[]{}/!@#$?|" alphabets := "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" diff --git a/internal/url.go b/internal/url.go index ded2c8b..e1f0cf0 100644 --- a/internal/url.go +++ b/internal/url.go @@ -49,19 +49,20 @@ func (g *UrlCommand) Init(args []string) error { } func (g *UrlCommand) Run() (err error) { - if g.op == "encode" { + switch g.op { + case "encode": s, err := g.encode(g.args[0]) if err != nil { return err } fmt.Println(s) - } else if g.op == "decode" { + case "decode": s, err := g.decode(g.args[0]) if err != nil { return err } fmt.Println(s) - } else { + default: err = errors.New("Unknown Op - " + g.op) } return err