Skip to content

Commit

Permalink
feat: init project (#1)
Browse files Browse the repository at this point in the history
* feat: init project
  • Loading branch information
kperreau authored Apr 18, 2024
1 parent aa3725a commit ebd4f98
Show file tree
Hide file tree
Showing 43 changed files with 3,700 additions and 2 deletions.
17 changes: 17 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.gitignore
.dockerignore
Dockerfile
.github/
.git/
*.log
.goac/
.goacproject.yaml
.semver.yaml
coverage.out
goac
*_test.go
README.md
LICENSE
Makefile
.DS_Store
.idea
2 changes: 2 additions & 0 deletions .github/auto_assign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
addReviewers: false
addAssignees: author
29 changes: 29 additions & 0 deletions .github/workflows/auto-clean-cache.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Cleanup branch caches
on:
pull_request:
types:
- closed

jobs:
autoCleanup:
runs-on: ubuntu-latest
steps:
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
49 changes: 49 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches:
- "**"

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22"
cache: false
check-latest: true

- name: Verify dependencies
run: |
go mod verify
git diff --exit-code
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
with:
version: "v1.55.2"
args: --timeout=10m

- name: Vet
run: make vet

- name: Test Format
run: |
go install mvdan.cc/gofumpt@latest
make format
- name: Unit Test
run: make ci-test
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@

# Go workspace file
go.work

.goac
goac
.idea
.DS_Store
18 changes: 18 additions & 0 deletions .goacproject.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: 1.0
name: goac
target:
build:
exec:
cmd: go
params:
- build
- -ldflags=-s -w
- -o
- "{{project-path}}/{{project-name}}"
- "{{project-path}}"
build-image:
envs:
- key: PROJECT_PATH
value: "{{project-path}}"
exec:
cmd: ./_scripts/build-image.sh
4 changes: 4 additions & 0 deletions .semver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
alpha: 0
beta: 0
rc: 0
release: v1.0.0
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM golang:1.22-bookworm AS builder

# Set Go env
ENV GOOS=linux CGO_ENABLED=0

WORKDIR /workspace

# Build Go binary
COPY . .
RUN --mount=type=cache,mode=0755,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
RUN --mount=type=cache,mode=0755,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 go build -ldflags="-s -w" -o /workspace/goac

# Deployment container
FROM gcr.io/distroless/static-debian12

COPY --from=builder /workspace/goac /goac
ENTRYPOINT ["/goac"]
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ 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.
SOFTWARE.
24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
tidy:
@go mod tidy
@gofumpt -l -w .

test:
@go test ./...

test-coverage:
go test ./... -coverprofile=coverage.out

dep:
go mod download

vet:
@go vet -unsafeptr=false ./...

lint:
@golangci-lint run

ci-test:
@go test -race -vet=off ./...

format:
@gofumpt -l .
161 changes: 160 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,160 @@
# goac
# Go Affected Cache (GOAC)

## About
Go Affected Cache (GOAC) is a tool tailored to optimize the build process for binaries and Docker images in monorepo setups through caching.

It generates and caches a hash based on the list of dependencies and files imported by each project within the monorepo. This functionality prevents unnecessary builds by detecting changes accurately, thus conserving time and resources.

Originally developed to address specific needs in my own project's architecture, GOAC might not directly align with every user's project structure and requirements, making its utility somewhat experimental.

## Features
Monorepo Efficiency: Specifically designed for monorepos, ensuring efficient handling of multiple interconnected projects.
Intelligent Change Detection: Utilizes hashes of dependencies and files to determine the necessity of builds.
Docker Integration: Optimizes Docker image creation by avoiding unnecessary builds and pushes, preventing redundant deployments.

## Installation
Follow these steps to install GOAC in your environment. Adjust as necessary for your specific setup.

```bash
go install github.com/kperreau/goac
```

## Configuration
Configuring GOAC is straightforward. You need to create a `.goacproject.yaml` file and place it at the root of each project/directory that requires a build.

### File example:
```yaml
# .goacproject.yaml

version: 1.0 # Please do not modify this value; keep it set to 1.0
name: goac # Specify the name of your project, service, or application here
target: # GOAC currently supports two targets: 'build' and 'build-image'
build: # This target compiles the Go binary
exec:
cmd: go # The command to execute for compilation; 'go' in this case
params: # Parameters to be added; the final command will be: go build -ldflags="-s -w" -o ./goac goac
- build
- -ldflags=-s -w
- -o
- "{{project-path}}/{{project-name}}"
- "{{project-path}}"
build-image: # This target builds the Docker image
envs:
- key: PROJECT_PATH
value: "{{project-path}}"
exec:
cmd: ./_scripts/build-image.sh # Shell script to execute for building the image
```
To see what the script that builds the image of this project looks like, take a look at this example: [build-image.sh](./_scripts/build-image.sh)
### Variables
The configuration file interprets variables that will automatically be replaced by their values.
Currently, there are two:
```
{{project-name}} # The name of the project
{{project-path}} # The path of the project
```

### Environnement
You can pass environment variables when executing GOAC, which will naturally be transmitted to the commands.
However, two environment variables are reserved, initialized, and transmitted by GOAC:
```
BUILD_NAME={{project-name}}
PROJECT_PATH={{project-path}}
```
If you run a shell script, you can use these 2 environment variables.

## Usage
GOAC offers commands such as affected and list to manage your monorepo effectively.

```
Usage:
goac [command]
Available Commands:
affected List affected projects
help Help about any command
list List projects
Flags:
-c, --concurrency int Max Concurrency (default 4)
--debug string Debug files loaded/hashed
-h, --help help for goac
-p, --projects string Filter by projects name
```

### Checking / Building Affected Projects
```
Usage:
goac affected [flags]
Examples:
goac affected -t build
Flags:
--binarycheck Affected if binary is missing
--dockerignore Read docker ignore (default true)
--dryrun Dry & run
-f, --force Force build
-h, --help help for affected
--stdout Print stdout of exec command
-t, --target string Target
Global Flags:
-c, --concurrency int Max Concurrency (default 4)
--debug string Debug files loaded/hashed
-p, --projects string Filter by projects name
```
Exemples:
```bash
goac affected -t build # build binary of affected project
goac affected -t build -p auth-service,docs # build binaries for auth-service and docs
goac affected -t build --force # build all binaries without checking affected projects
goac affected -t build --debug=name,hashed -p docs # build project docs with debug to display project name and hashed files
```

### Listing Projects
To list all projects configured in your monorepo based on the `.goacproject.yaml`:

```
Usage:
goac list [flags]
Examples:
goac list
Flags:
-h, --help help for list
Global Flags:
-c, --concurrency int Max Concurrency (default 4)
--debug string Debug files loaded/hashed
-p, --projects string Filter by projects name
```

Exemples:
```bash
goac list
```

### Common Options
--debug [types]: Controls the verbosity of command output, useful for debugging.
Available types: name,includes,excludes,local,dependencies

## Contribution
Contributions are welcome! If you'd like to contribute, please follow these steps:

Fork the project
Create your feature branch (git checkout -b feature/AmazingFeature)
Commit your changes (git commit -m 'Add some AmazingFeature')
Push to the branch (git push origin feature/AmazingFeature)
Open a Pull Request

## Authors
- [@kperreau](https://www.github.com/kperreau)

## License
Distributed under the MIT License. See [LICENSE](./LICENSE) for more information.
33 changes: 33 additions & 0 deletions _scripts/build-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

set -e

: "${PUSH_IMAGE="false"}"

: "${REPOSITORY="kperreau/goac"}"

: "${PROJECT_PATH="."}" # project path (must be where the Dockerfile is)

DOCKERFILE="${PROJECT_PATH}/Dockerfile"

GIT_VERSION=$(git rev-parse --short=7 HEAD)

dockerCmd=(docker buildx build --platform="linux/amd64,linux/arm64" --network host)

if [[ "${PUSH_IMAGE}" == "true" ]]; then
dockerCmd+=(--push);
fi

# print cmd
echo "${dockerCmd[@]}" \
-t "${REPOSITORY}:latest" \
-t "${REPOSITORY}:${GIT_VERSION}" \
-f "${DOCKERFILE}" \
.

# run docker build
"${dockerCmd[@]}" \
-t "${REPOSITORY}:latest" \
-t "${REPOSITORY}:${GIT_VERSION}" \
-f "${DOCKERFILE}" \
.
Loading

0 comments on commit ebd4f98

Please sign in to comment.