Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

feat: grpc server and greeting service #3

Merged
merged 5 commits into from
Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,4 @@ jobs:
with:
go-version: 1.18
- run: go version
- run: go build -v ./...

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-go@v3
with:
go-version: 1.18
- run: go version
- run: go test -v ./...
- run: go build ./cmd/...
32 changes: 32 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,36 @@ jobs:
go-version: 1.18
- uses: golangci/golangci-lint-action@v3
with:
version: v1.49.0
only-new-issues: true

buf:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: bufbuild/buf-setup-action@v1
with:
version: v1.8.0
github_token: ${{ github.token }}
- uses: bufbuild/buf-lint-action@v1
with:
input: proto/internal

buf-breaking:
runs-on: ubuntu-latest
if: false
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: bufbuild/buf-setup-action@v1
with:
version: v1.8.0
github_token: ${{ github.token }}
- uses: bufbuild/buf-breaking-action@v1
with:
input: proto/internal
against: https://github.com/$GITHUB_REPOSITORY.git#branch=main,ref=HEAD~1,subdir=proto/internal
3 changes: 1 addition & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: goreleaser/goreleaser-action@v3
with:
distribution: goreleaser
version: latest
version: v1.11.2
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3 changes: 1 addition & 2 deletions .github/workflows/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ on:
branches:
- main
pull_request:
workflow_dispatch:

permissions:
contents: read
pull-requests: write

jobs:
scan:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: test

on:
push:
branches:
- main
pull_request:

permissions:
contents: read

jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-go@v3
with:
go-version: 1.18
- run: go version
- run: go test -failfast -timeout 30s ./...
3 changes: 3 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
---
run:
go: "1.18"

linters:
disable-all: true
enable:
Expand Down
69 changes: 1 addition & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,4 @@

This repository is a playground for experimenting with CI/CD in Go.

## Usage

It's all based on pushes and pull requests. Here is the list of actions triggered based on each event:

- If you push a tag to the repository: `lint`, `release` and `security` actions are triggered.
- If you push a commit to the `main` branch or open a pull request: `build`, `lint` and `security` actions are triggered.

You need to configure the following secrets in the repository settings:

- `DOCKERHUB_USERNAME`: The username of the Docker Hub account.
- `DOCKERHUB_TOKEN`: The token of the Docker Hub account.
- `GITLEAKS_NOTIFY_USER_LIST`: The list of users to notify when a secret leak is found.

## Actions

- The [build action](.github/workflows/build.yml) builds the binaries and runs the tests.
- The [lint action](.github/workflows/lint.yml) runs `golangci-lint` on the code. ([example](https://github.com/calmonr/cicd/pull/1))
- The [release action](.github/workflows/release.yml) runs `goreleaser` to build and publish the binaries. ([examples](https://github.com/calmonr/cicd/releases))
- The [security action](.github/workflows/security.yml) runs `gitleaks` to check for secret leaks. ([example](https://github.com/calmonr/cicd/pull/2))

## Tools

> You can use [act](https://github.com/nektos/act) to run GitHub Actions locally.

- [x] [GitHub Actions](https://docs.github.com/pt/actions)
- [x] [GoReleaser](https://goreleaser.com/)
- [x] [golangci-lint](https://golangci-lint.run/)
- [x] [EditorConfig](https://editorconfig.org/)
- [x] [Gitleaks](https://gitleaks.io/)
- [ ] [Cobra](https://cobra.dev/)
- [ ] [gRPC](https://grpc.io/)
- [ ] [Buf](https://buf.build/)
- [ ] [Dagger](https://dagger.io/)
- [ ] [Task](https://taskfile.dev/)
- [ ] [UPX](https://github.com/upx/upx)

## Plans

- [ ] [CLI completion](https://carlosbecker.com/posts/golang-completions-cobra/)
- [ ] [Versioning](https://goreleaser.com/cookbooks/using-main.version)
- [x] [Docker images](https://goreleaser.com/customization/docker/)
- [x] GitHub Container Registry
- [x] Docker Hub
- [ ] Sign [checksums, artifacts](https://goreleaser.com/customization/sign/), [Docker images and manifests](https://goreleaser.com/customization/docker_sign/)
- [x] Tests

> Probably more to come.

## Tips

You should use [pre-commit](https://pre-commit.com/) to run linting and testing on your project, this way you can catch problems early.

> I'm not going to do that here (we want action :eyes:), but you should.

```yaml
---
repos:
- repo: https://github.com/golangci/golangci-lint
rev: v1.48.0
hooks:
- id: golangci-lint
- repo: https://github.com/zricethezav/gitleaks
rev: v8.12.0
hooks:
- id: gitleaks
default_install_hook_types: [pre-commit]
minimum_pre_commit_version: 2.20.0
```
> This documentation is being completely rewritten explaining better the purpose of this repository and how to use it.
13 changes: 13 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
version: v1
managed:
enabled: true
go_package_prefix:
default: github.com/calmonr/cicd/pkg/proto
plugins:
- name: go
out: .
opt: paths=source_relative
- name: go-grpc
out: .
opt: paths=source_relative
4 changes: 4 additions & 0 deletions buf.work.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
version: v1
directories:
- proto/internal
23 changes: 23 additions & 0 deletions cmd/playground/app/command/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package command

import (
"github.com/calmonr/cicd/internal/command"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func NewRoot(r command.Runnable, f *pflag.FlagSet) *cobra.Command {
cmd := &cobra.Command{
Use: "playground",
Short: "Go CI/CD Playground.",
Long: `Go CI/CD Playground.`,
Version: "1.0.0",
RunE: r,
SilenceErrors: true,
SilenceUsage: true,
}

cmd.Flags().AddFlagSet(f)

return cmd
}
17 changes: 17 additions & 0 deletions cmd/playground/app/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app

import "github.com/spf13/viper"

type Config struct {
GRPCServer struct {
Address, Network string
}
}

func (c Config) Fill() Config {
// grpc server
c.GRPCServer.Address = viper.GetString(PrefixGRPCServer + SuffixAddress)
c.GRPCServer.Network = viper.GetString(PrefixGRPCServer + SuffixNetwork)

return c
}
24 changes: 24 additions & 0 deletions cmd/playground/app/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package app

import (
"github.com/spf13/pflag"
)

const (
PrefixGRPCServer = "grpc-server."
)

const (
SuffixAddress = "address"
SuffixNetwork = "network"
)

func Flags() *pflag.FlagSet {
f := new(pflag.FlagSet)

// grpc server
f.String(PrefixGRPCServer+SuffixAddress, ":50051", "address to listen on")
f.String(PrefixGRPCServer+SuffixNetwork, "tcp", "network to listen on")

return f
}
93 changes: 93 additions & 0 deletions cmd/playground/app/runnable/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package runnable

import (
"context"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"

"github.com/calmonr/cicd/cmd/playground/app"
"github.com/calmonr/cicd/internal/cli"
"github.com/calmonr/cicd/internal/command"
"github.com/calmonr/cicd/internal/logger"
"github.com/calmonr/cicd/internal/service/greeting"
greetingv1 "github.com/calmonr/cicd/pkg/proto/greeting/v1"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

func NewRoot() command.Runnable {
return func(cmd *cobra.Command, args []string) error {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()

logger, err := logger.New()
if err != nil {
return fmt.Errorf("could not create logger: %w", err)
}

defer func() {
// it should be safe to ignore according to https://github.com/uber-go/zap/issues/328
_ = logger.Sync()
}()

// read config from file if the config file is specified
{
if file := viper.GetString(cli.ConfigFileFlag); file != "" {
viper.SetConfigFile(file)

if err := viper.ReadInConfig(); err != nil {
log.Fatalf("could not read config file: %v", err)
}
}
}

cfg := new(app.Config).Fill()

listener, err := net.Listen(cfg.GRPCServer.Network, cfg.GRPCServer.Address)
if err != nil {
return fmt.Errorf("could not listen on %s: %w", cfg.GRPCServer.Address, err)
}

server := grpc.NewServer()

greetingv1.RegisterGreetingServiceServer(server, &greeting.Service{})

reflection.Register(server)

g, ctx := errgroup.WithContext(ctx)

g.Go(func() error {
logger.Info("serving grpc server", zap.String("address", cfg.GRPCServer.Address))

if err := server.Serve(listener); err != nil {
return fmt.Errorf("could not serve grpc: %w", err)
}

return nil
})

g.Go(func() error {
<-ctx.Done()

logger.Info("gracefully stopping the application")

server.GracefulStop()

return nil
})

if err := g.Wait(); err != nil {
return fmt.Errorf("could not stop application: %w", err)
}

return nil
}
}
Loading