diff --git a/README.md b/README.md index ef2dcda..2073b3e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,197 @@ # Go CI/CD Playground -> This documentation is being completely rewritten explaining better the purpose of this repository and how to use it. +This repository is a playground for experimenting with CI/CD in Go. It is a well-structured command-line application that serves a gRPC service and is an excellent example of how to structure a Go project. + +It is not intended to be a complete application but a starting point for your projects. + +## Table of Contents + +- [CI/CD](#cicd) + - [Actions](#actions) + - [Release](#release) +- [Application](#application) + - [Running the application](#running-the-application) + - [Running locally](#running-locally) + - [Running in a Docker container](#running-in-a-docker-container) + - [Development](#development) + - [Protobuf](#protobuf) +- [Tools](#tools) +- [Tips](#tips) +- [Code of Conduct](#code-of-conduct) + +## CI/CD + +It is all based on pushes and pull requests. Here is the list of actions triggered based on each event: + +- When a tag is pushed: `lint`, `release`, and `security` actions are triggered. +- When a commit is pushed to the `main` branch or a pull request is opened: `build`, `lint`, `security`, and `test` actions are triggered. + +> **Note** +> +> 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 for checking the code. +- The [lint action](.github/workflows/lint.yml) runs `golangci-lint` on the code and `buf` on the protobuf files ([example](https://github.com/calmonr/cicd/pull/3)). +- 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)). +- The [test action](.github/workflows/test.yml) runs the unit tests. + +> **Note** +> +> You can use [act](https://github.com/nektos/act) to run GitHub Actions locally. + +#### Release + +`goreleaser` is the core of the release process. It is configured in the [`.goreleaser.yaml`](.goreleaser.yaml) file. + +For multiple architectures, all Docker images are pushed to the GitHub Container Registry and Docker Hub. + +The binary is built using the `ldflags` flag to embed the version, commit and build time in the binary. The `version` command or the `--version` can print this information. + +There are also a few completion scripts for the `bash`, `zsh`, and `fish` shells in the released archives. + +> **Note** +> +> The releases are created as drafts. You need to manually publish them, allowing you to review the release notes before publishing. + +## Application + +The application is a **simple** gRPC server with a greeting service. It has a single endpoint, `Hi`, which takes a `HiRequest` and returns a `HiResponse`. The `HiRequest` contains a `name` field, which is used to construct the `HiResponse` message. + +### Running the application + +You can either run the application locally or in a Docker container. + +#### Running locally + +It can be configured using environment variables or a configuration file. The configuration file will only be used if the `--config-file` flag is provided. + +> **Note** +> +> There is a sample configuration file in the `configs` directory. + +Using environment variables: + +```bash +export PLAYGROUND_LOG_LEVEL=info +export PLAYGROUND_GRPC_SERVER_ADDRESS=:50051 +export PLAYGROUND_GRPC_SERVER_NETWORK=tcp + +go run ./cmd/playground/main.go +``` + +Using a configuration file: + +```bash +go run ./cmd/playground/main.go --config-file ./configs/development.yaml +``` + +#### Running in a Docker container + +The [Dockerfile](./Dockerfile) is located at the repository's root. It is a multi-stage build that builds the binary and then copies it to a scratch image. + +First, we need to build the image: + +```bash +docker build -t playground . +``` + +Then we can run the container: + +```bash +docker run \ + -e PLAYGROUND_LOG_LEVEL=info \ + -e PLAYGROUND_GRPC_SERVER_ADDRESS=:50051 \ + -e PLAYGROUND_GRPC_SERVER_NETWORK=tcp \ + -p 50051:50051 \ + playground +``` + +> **Note** +> +> There is a `docker-compose.yml` that you can use as well. +> +> ```bash +> docker-compose up -d +> ``` +> +> You can switch from `docker` to `nerdctl` if you use Containerd. + +### Development + +You will need to install a few tools before you can start developing the application. + +```bash +sh ./scripts/install-tools.sh +``` + +#### Protobuf + +[Buf](https://docs.buf.build/introduction) is used to lint the protobuf definitions and generate source code from them. + +You can find the protobuf definitions in the `proto` directory. + +Before we continue, let us verify that everything is set up correctly: + +```console +buf build +``` + +You can run all of the configured lint rules by running this command: + +```console +buf lint +``` + +Now we can generate the source code for our service: + +```console +buf generate -o pkg/proto proto/internal +``` + +## Tools + +Here is a list of tools used in this repository: + +> **Warning** +> +> I might have missed some, so feel free to open a pull request if you think something is missing. :nerd_face: + +- [x] [GoReleaser](https://goreleaser.com/) +- [x] [golangci-lint](https://golangci-lint.run/) +- [x] [EditorConfig](https://editorconfig.org/) +- [x] [Gitleaks](https://gitleaks.io/) +- [x] [Cobra](https://cobra.dev/) +- [x] [Viper](https://github.com/spf13/viper) +- [x] [zap](https://github.com/uber-go/zap) +- [x] [gRPC](https://grpc.io/) + - [x] [Buf](https://buf.build/) + +## Tips + +It would be best if you used [pre-commit](https://pre-commit.com/) to run linting and testing on your project; this way, you can catch problems before they are committed. + +```yaml +--- +repos: + - repo: https://github.com/golangci/golangci-lint + rev: v1.49.0 + hooks: + - id: golangci-lint + - repo: https://github.com/zricethezav/gitleaks + rev: v8.13.0 + hooks: + - id: gitleaks +default_install_hook_types: [pre-commit] +minimum_pre_commit_version: 2.20.0 +``` + +## Code of Conduct + +This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. diff --git a/config/.gitignore b/configs/.gitignore similarity index 100% rename from config/.gitignore rename to configs/.gitignore diff --git a/config/sample.yaml b/configs/sample.yaml similarity index 100% rename from config/sample.yaml rename to configs/sample.yaml diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..17aa8df --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,11 @@ +--- +version: "3" +services: + playground: + image: calmonr/cicd:latest + ports: + - 50051:50051 + environment: + PLAYGROUND_LOG_LEVEL: info + PLAYGROUND_GRPC_SERVER_ADDRESS: 50051 + PLAYGROUND_GRPC_SERVER_NETWORK: tcp