From f6af583408f417361ac83daf67d66ec824daa5e1 Mon Sep 17 00:00:00 2001 From: Ruidy Date: Thu, 31 Mar 2022 11:37:02 -0400 Subject: [PATCH] Pipe (#26) * rename to pipe * add security scan * use var in Makefile --- .dockerignore | 3 +- .github/workflows/codeql-analysis.yml | 39 ---------- .gitignore | 1 + .gitmodules | 3 - Dockerfile | 3 +- Makefile | 11 ++- README.md | 10 +-- docs/content/_index.md | 4 +- .../chaining.md => pipe/new_pipe.md} | 8 +- each.go | 2 +- examples/{chaining.go => pipe.go} | 6 +- examples/{chaining_test.go => pipe_test.go} | 4 +- chain/chain.go => pipe.go | 76 +++++++++---------- chain/chain_test.go => pipe_test.go | 28 +++---- 14 files changed, 82 insertions(+), 116 deletions(-) delete mode 100644 .gitmodules rename docs/content/{chaining/chaining.md => pipe/new_pipe.md} (70%) rename examples/{chaining.go => pipe.go} (71%) rename examples/{chaining_test.go => pipe_test.go} (52%) rename chain/chain.go => pipe.go (55%) rename chain/chain_test.go => pipe_test.go (82%) diff --git a/.dockerignore b/.dockerignore index 1418c3e..88ad044 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,4 +4,5 @@ .git* .idea/ .golangci.yml -coverage.out \ No newline at end of file +coverage.out +.trivycache/ diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d8a97bc..ed3b1e5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,25 +1,11 @@ -# 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. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# name: "CodeQL" - on: push: branches: [ main ] pull_request: - # The branches below must be a subset of the branches above branches: [ main ] schedule: - cron: '24 15 * * 6' - jobs: analyze: name: Analyze @@ -28,43 +14,18 @@ jobs: actions: read contents: read security-events: write - strategy: fail-fast: false matrix: language: [ 'go' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support - 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/.gitignore b/.gitignore index 5e2dba5..0fd6007 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ Network Trash Folder Temporary Items .apdisk docs/public +.trivycache/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 4a2ae0d..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "docs/themes/compose"] - path = docs/themes/compose - url = https://github.com/onweru/compose/ diff --git a/Dockerfile b/Dockerfile index d37e86c..4632d29 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,9 @@ FROM golang:1.18-alpine ENV CGO_ENABLED 0 ENV GOOS linux +ENV GOARCH amd64 -RUN apk update --no-cache +RUN apk upgrade --no-cache WORKDIR /lib diff --git a/Makefile b/Makefile index 885d624..3de24bd 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,17 @@ TEST = "go test ./... -coverpkg=./... -coverprofile coverage.out -covermode=count; go tool cover -func coverage.out; rm coverage.out" +IMAGE=underscore build: - docker build -t underscore:latest . + docker build -t $(IMAGE):latest . test: build - docker run --name underscore --rm -i -t underscore sh -c $(TEST) + docker run --name $(IMAGE) --rm -i -t $(IMAGE) sh -c $(TEST) + +scan: + trivy --cache-dir .trivycache/ image --exit-code 0 --no-progress --severity CRITICAL $(IMAGE) + +scan-config: + trivy config . docs: cd docs && hugo server -D diff --git a/README.md b/README.md index 7e39ba9..0176efc 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# Underscore +# _Underscore ![License](https://img.shields.io/github/license/rjNemo/underscore?style=for-the-badge) [![Go version](https://img.shields.io/github/go-mod/go-version/rjNemo/underscore?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/rjNemo/underscore) ![Go report](https://goreportcard.com/badge/github.com/rjNemo/underscore?style=for-the-badge) ![test coverage](https://img.shields.io/codecov/c/github/rjNemo/underscore?style=for-the-badge&logo=codecov) -![underscore](https://socialify.git.ci/rjNemo/underscore/image?description=1&descriptionEditable=Useful%20functional%20programming%20helpers%20for%20Go%201.18%20and%20beyond&font=Raleway&language=1&logo=https%3A%2F%2Fraw.githubusercontent.com%2FrjNemo%2Funderscore%2Fmain%2Fdocs%2Fstatic%2Flogo.png&owner=1&pattern=Floating%20Cogs&stargazers=1&theme=Light) +![underscore](https://socialify.git.ci/rjNemo/underscore/image?description=1&font=KoHo&language=1&logo=https%3A%2F%2Fraw.githubusercontent.com%2FrjNemo%2Funderscore%2Fmain%2Fdocs%2Fstatic%2Flogo.png&owner=1&pattern=Floating%20Cogs&stargazers=1&theme=Dark) `underscore` is a `Go` library providing useful functional programming helpers without extending any built-in objects. @@ -82,7 +82,7 @@ make test ## Functions -`underscore` provides 100s of functions that support your favorite functional helpers +`underscore` provides many of functions that support your favorite functional helpers ### Collections @@ -98,9 +98,9 @@ make test - `Partition` - `Reduce` -### Chaining +### Pipe -Calling `chain.Of` will cause all future method calls to return wrapped values. When you've finished the computation, +Calling `NewPipe` will cause all future method calls to return wrapped values. When you've finished the computation, call `Value` to retrieve the final value. Methods not returning a slice such as `Reduce`, `All`, `Any`, will break the `Chain` and return `Value` instantly. diff --git a/docs/content/_index.md b/docs/content/_index.md index 88ef255..f717fe2 100644 --- a/docs/content/_index.md +++ b/docs/content/_index.md @@ -1,5 +1,5 @@ --- -title: underscore +title: _Underscore --- ![License](https://img.shields.io/github/license/rjNemo/underscore?style=for-the-badge) @@ -7,7 +7,7 @@ title: underscore ![Go report](https://goreportcard.com/badge/github.com/rjNemo/underscore?style=for-the-badge) ![test coverage](https://img.shields.io/codecov/c/github/rjNemo/underscore?style=for-the-badge&logo=codecov) -![underscore](https://socialify.git.ci/rjNemo/underscore/image?description=1&font=Raleway&language=1&logo=https%3A%2F%2Fgithub.com%2FrjNemo%2Funderscore%2Fblob%2Fmain%2Fdocs%2Fstatic%2Flogo.png%3Fraw%3Dtrue&name=1&pattern=Floating%20Cogs&theme=Light) +![underscore](https://socialify.git.ci/rjNemo/underscore/image?description=1&font=KoHo&language=1&logo=https%3A%2F%2Fraw.githubusercontent.com%2FrjNemo%2Funderscore%2Fmain%2Fdocs%2Fstatic%2Flogo.png&owner=1&pattern=Floating%20Cogs&stargazers=1&theme=Dark) `underscore` is a `Go` library providing useful functional programming helpers without extending any built-in objects. diff --git a/docs/content/chaining/chaining.md b/docs/content/pipe/new_pipe.md similarity index 70% rename from docs/content/chaining/chaining.md rename to docs/content/pipe/new_pipe.md index 98d3957..fb92af5 100644 --- a/docs/content/chaining/chaining.md +++ b/docs/content/pipe/new_pipe.md @@ -1,10 +1,10 @@ --- -title: "Of" +title: "NewPipe" date: 2021-12-31T13:11:41-04:00 --- -Calling `Of` will cause all future method calls to return wrapped objects. When you've finished the computation, +Calling `NewPipe` will cause all future method calls to return wrapped objects. When you've finished the computation, call `Value` to retrieve the final value. Methods not returning a collection such as `Reduce`, `All`, `Any`, will break the chain and return `Value` instantly. @@ -14,11 +14,11 @@ package main import ( "fmt" - "github.com/rjNemo/underscore/chain" + u "github.com/rjNemo/underscore" ) func main() { - sum := chain.Of([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}). + sum := u.NewPipe([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}). // filter even numbers from the slice Filter(func(n int) bool { return n%2 == 0 }). // square every number in the slice diff --git a/each.go b/each.go index ea04159..60277b2 100644 --- a/each.go +++ b/each.go @@ -1,7 +1,7 @@ package underscore // Each iterates over a slice of elements, yielding each in turn to an action function. -// Returns the slice for chaining. +// Returns the slice for piping. func Each[T any](values []T, action func(T)) []T { for _, v := range values { action(v) diff --git a/examples/chaining.go b/examples/pipe.go similarity index 71% rename from examples/chaining.go rename to examples/pipe.go index 2e863f3..e32a6b8 100644 --- a/examples/chaining.go +++ b/examples/pipe.go @@ -1,11 +1,11 @@ package examples import ( - "github.com/rjNemo/underscore/chain" + u "github.com/rjNemo/underscore" ) -func chaining() int { - return chain.Of([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}). +func piping() int { + return u.NewPipe([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}). // filter even numbers from the slice Filter(func(n int) bool { return n%2 == 0 }). // square every number in the slice diff --git a/examples/chaining_test.go b/examples/pipe_test.go similarity index 52% rename from examples/chaining_test.go rename to examples/pipe_test.go index 1dc5127..6b26ee4 100644 --- a/examples/chaining_test.go +++ b/examples/pipe_test.go @@ -6,6 +6,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestChainingExample(t *testing.T) { - assert.Equal(t, 120, chaining()) +func TestPipingExample(t *testing.T) { + assert.Equal(t, 120, piping()) } diff --git a/chain/chain.go b/pipe.go similarity index 55% rename from chain/chain.go rename to pipe.go index 71be2c3..7fde98a 100644 --- a/chain/chain.go +++ b/pipe.go @@ -1,94 +1,92 @@ -package chain +package underscore import ( "golang.org/x/exp/constraints" - - u "github.com/rjNemo/underscore" ) -type Chain[T constraints.Ordered] struct { +type Pipe[T constraints.Ordered] struct { Value []T } -// Of starts a Chain. All future method calls will return Chain structs. When you've finished the computation, +// NewPipe starts a Pipe. All future method calls will return Pipe structs. When you've finished the computation, // call Value to retrieve the final value. // -// Methods not returning a slice such as Reduce, All, Any, will break the chain and return Value instantly. -func Of[T constraints.Ordered](value []T) Chain[T] { - return Chain[T]{Value: value} +// Methods not returning a slice such as Reduce, All, Any, will break the Pipe and return Value instantly. +func NewPipe[T constraints.Ordered](value []T) Pipe[T] { + return Pipe[T]{Value: value} } // All returns true if all the values in the slice pass the predicate truth test. // Short-circuits and stops traversing the slice if a false element is found. -// Breaks the Chain. -func (c Chain[T]) All(predicate func(T) bool) bool { - return u.All(c.Value, predicate) +// Breaks the Pipe. +func (c Pipe[T]) All(predicate func(T) bool) bool { + return All(c.Value, predicate) } // Any returns true if any of the values in the slice pass the predicate truth test. // Short-circuits and stops traversing the slice if a true element is found. -// Breaks the Chain. -func (c Chain[T]) Any(predicate func(T) bool) bool { - return u.Any(c.Value, predicate) +// Breaks the Pipe. +func (c Pipe[T]) Any(predicate func(T) bool) bool { + return Any(c.Value, predicate) } -// Contains returns true if the value is present in the slice and breaks the Chain. -func (c Chain[T]) Contains(value T) bool { - return u.Contains(c.Value, value) +// Contains returns true if the value is present in the slice and breaks the Pipe. +func (c Pipe[T]) Contains(value T) bool { + return Contains(c.Value, value) } // Each iterates over a slice of elements, yielding each in turn to an action function. -// Breaks the Chain. -func (c Chain[T]) Each(action func(T)) { - u.Each(c.Value, action) +// Breaks the Pipe. +func (c Pipe[T]) Each(action func(T)) { + Each(c.Value, action) } // Filter looks through each value in the slice, returning a slice of all the values that pass a truth test (predicate). -func (c Chain[T]) Filter(predicate func(n T) bool) Chain[T] { - return Chain[T]{Value: u.Filter(c.Value, predicate)} +func (c Pipe[T]) Filter(predicate func(n T) bool) Pipe[T] { + return Pipe[T]{Value: Filter(c.Value, predicate)} } // Find looks through each value in the slice, returning the first one that passes a truth test (predicate), // or the default value for the type and an error if no value passes the test. // The function returns as soon as it finds an acceptable element, and doesn't traverse the entire slice. -// Breaks the Chain. -func (c Chain[T]) Find(predicate func(n T) bool) (T, error) { - return u.Find(c.Value, predicate) +// Breaks the Pipe. +func (c Pipe[T]) Find(predicate func(n T) bool) (T, error) { + return Find(c.Value, predicate) } // Map produces a new slice of values by mapping each value in the slice through // a transform function. // // TODO: Move from T to P. -func (c Chain[T]) Map(transform func(n T) T) Chain[T] { - return Chain[T]{Value: u.Map(c.Value, transform)} +func (c Pipe[T]) Map(transform func(n T) T) Pipe[T] { + return Pipe[T]{Value: Map(c.Value, transform)} } // Max returns the maximum value in the slice. // This function can currently only compare numbers reliably. // This function uses operator <. -// Breaks the Chain. -func (c Chain[T]) Max() T { - return u.Max(c.Value) +// Breaks the Pipe. +func (c Pipe[T]) Max() T { + return Max(c.Value) } // Min returns the minimum value in the slice. // This function can currently only compare numbers reliably. // This function uses operator <. -// Breaks the Chain. -func (c Chain[T]) Min() T { - return u.Min(c.Value) +// Breaks the Pipe. +func (c Pipe[T]) Min() T { + return Min(c.Value) } // Partition splits the slice into two slices: one whose elements all satisfy predicate // and one whose elements all do not satisfy predicate. -// Breaks the Chain. -func (c Chain[T]) Partition(predicate func(T) bool) ([]T, []T) { - return u.Partition(c.Value, predicate) +// Breaks the Pipe. +func (c Pipe[T]) Partition(predicate func(T) bool) ([]T, []T) { + return Partition(c.Value, predicate) } -// Reduce combine a list of values into a single value and breaks the Chain. +// Reduce combine a list of values into a single value and breaks the Pipe. // acc is the initial state, and each successive step of it should be returned by the reduction function. -func (c Chain[T]) Reduce(reducer func(n, acc T) T, acc T) T { - return u.Reduce(c.Value, reducer, acc) +func (c Pipe[T]) Reduce(reducer func(n, acc T) T, acc T) T { + return Reduce(c.Value, reducer, acc) } diff --git a/chain/chain_test.go b/pipe_test.go similarity index 82% rename from chain/chain_test.go rename to pipe_test.go index f357922..e74182f 100644 --- a/chain/chain_test.go +++ b/pipe_test.go @@ -1,18 +1,18 @@ -package chain_test +package underscore_test import ( "testing" - "github.com/stretchr/testify/assert" + u "github.com/rjNemo/underscore" - "github.com/rjNemo/underscore/chain" + "github.com/stretchr/testify/assert" ) func TestChainFilter(t *testing.T) { want := []int{2, 4, 6, 8} assert.Equal(t, want, - chain.Of(nums).Filter(isEven).Value, + u.NewPipe(nums).Filter(isEven).Value, ) } @@ -20,7 +20,7 @@ func TestChainFilterMap(t *testing.T) { want := []int{4, 16, 36, 64} assert.Equal(t, want, - chain.Of(nums). + u.NewPipe(nums). Filter(isEven). Map(toSquare). Value) @@ -30,14 +30,14 @@ func TestChainFilterMapReduce(t *testing.T) { want := 120 assert.Equal(t, want, - chain.Of(nums). + u.NewPipe(nums). Filter(isEven). Map(toSquare). Reduce(sum, 0)) } func TestChainFilterMapContains(t *testing.T) { - assert.True(t, chain.Of(nums). + assert.True(t, u.NewPipe(nums). Filter(isEven). Map(toSquare). Contains(16)) @@ -46,7 +46,7 @@ func TestChainFilterMapContains(t *testing.T) { func TestChainFilterMapEach(t *testing.T) { want := []int{5, 17, 37, 65} res := make([]int, 0) - chain.Of(nums). + u.NewPipe(nums). Filter(isEven). Map(toSquare). Each(func(n int) { res = append(res, n+1) }) @@ -54,14 +54,14 @@ func TestChainFilterMapEach(t *testing.T) { } func TestChainFilterMapAll(t *testing.T) { - assert.True(t, chain.Of(nums). + assert.True(t, u.NewPipe(nums). Filter(isEven). Map(toSquare). All(func(n int) bool { return n%4 == 0 })) } func TestChainFilterMapFind(t *testing.T) { - n, err := chain.Of(nums). + n, err := u.NewPipe(nums). Filter(isEven). Map(toSquare). Find(func(n int) bool { return n%4 == 0 }) @@ -71,7 +71,7 @@ func TestChainFilterMapFind(t *testing.T) { func TestChainFilterMapMax(t *testing.T) { want := 64 - assert.Equal(t, want, chain.Of(nums). + assert.Equal(t, want, u.NewPipe(nums). Filter(isEven). Map(toSquare). Max()) @@ -79,7 +79,7 @@ func TestChainFilterMapMax(t *testing.T) { func TestChainFilterMapMin(t *testing.T) { w := 4 - assert.Equal(t, w, chain.Of(nums). + assert.Equal(t, w, u.NewPipe(nums). Filter(isEven). Map(toSquare). Min()) @@ -88,7 +88,7 @@ func TestChainFilterMapMin(t *testing.T) { func TestChainFilterMapPartition(t *testing.T) { wantLeft := []int{4, 16} wantRight := []int{36, 64} - left, right := chain.Of(nums). + left, right := u.NewPipe(nums). Filter(isEven). Map(toSquare). Partition(func(n int) bool { return n < 20 }) @@ -98,7 +98,7 @@ func TestChainFilterMapPartition(t *testing.T) { } func TestChainFilterMapAny(t *testing.T) { - assert.True(t, chain.Of(nums). + assert.True(t, u.NewPipe(nums). Filter(isEven). Map(toSquare). Any(func(n int) bool { return n%64 == 0 }))