Skip to content

Commit

Permalink
chore 🧹: initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Hang <[email protected]>
  • Loading branch information
Banh-Canh committed Dec 22, 2024
0 parents commit 2bd85e2
Show file tree
Hide file tree
Showing 17 changed files with 761 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 99
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 99
24 changes: 24 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
changelog:
exclude:
labels:
- ignore-for-release
authors:
- Victor Hang
categories:
- title: Breaking Changes 🛠
labels:
- Semver-Major
- breaking-change
- title: Features 🎉
labels:
- Semver-Minor
- enhancement
- title: Enhancements ✨
labels:
- '*'
exclude:
labels:
- dependencies
- title: 👒 Dependencies
labels:
- dependencies
18 changes: 18 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: GoReleaser Dry Run
on:
pull_request:
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22.6'
- name: Run GoReleaser (dry run)
uses: goreleaser/goreleaser-action@v6
with:
args: release --snapshot # Perform a dry run
version: '~> v2'
33 changes: 33 additions & 0 deletions .github/workflows/linting.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Go Lint and Format Check
on:
pull_request:
jobs:
lint_and_format:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22.6'
- name: Install Tools
run: |
go install mvdan.cc/gofumpt@latest
go install github.com/segmentio/golines@latest
- name: Run gofumpt
run: |
gofumpt -d . | tee gofumpt_output.txt
if [ -s gofumpt_output.txt ]; then
echo "gofumpt found issues:"
cat gofumpt_output.txt
exit 1
fi
- name: Run golines
run: |
golines --max-len=140 . --dry-run | tee golines_output.txt
if [ -s golines_output.txt ]; then
echo "golines found lines exceeding 140 characters:"
cat golines_output.txt
exit 1
fi
28 changes: 28 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: goreleaser
on:
push:
tags:
- '*'
permissions:
contents: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22.6'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: '~> v2'
args: release --clean
workdir: ./
env:
GITHUB_TOKEN: ${{ secrets.DIDACTIKLABS_GITHUB_TOKEN }}
18 changes: 18 additions & 0 deletions .github/workflows/unittest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Go Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22.6'
- name: Run tests with coverage
run: |
go test -coverprofile=coverage.out ./...
32 changes: 32 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: 2
before:
hooks:
- go mod tidy
builds:
- binary: ginx
main: ./
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
- arm
ldflags:
- -s -w -X github.com/didactiklabs/ginx/cmd.version=v{{- .Version }}
archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_v{{- .Version }}_ {{- title .Os }}_ {{- if eq .Arch "amd64" }}x86_64 {{- else if eq .Arch "386" }}i386 {{- else }}{{ .Arch }}{{ end }} {{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
files:
- README.md
- LICENSE
- docs/*
Empty file added LICENSE
Empty file.
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<div align="center">
<h1> Ginx </h1>

![star]
[![Downloads][downloads-badge]][releases]
![version]

</div>

**ginx** is a lightweight CLI tool designed to monitor changes in remote Git repositories and execute custom commands when updates occur. It is ideal for automating tasks, deploying applications, or triggering workflows whenever the target repository is updated.

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [License](#license)

## Features

- **Monitor Remote Repositories**: Watch specific branches for updates.
- **Custom Commands**: Execute any command when changes are detected.
- **Configurable Intervals**: Set the polling frequency for repository checks.
- **Flexible Logging**: Adjust log levels for better visibility or minimal noise.
- **Version Display**: Check the current version of the tool.

## Installation

To install `ytui`, follow the instructions for your operating system.
Ensure that you have the required dependencies installed.

1. **Install binary**

ginx runs on most major platforms. If your platform isn't listed below,
please [open an issue][issues].

Please note that binaries are available on the release pages, you can extract the archives for your
platform and manually install it.

## Usage

See [Documentations](docs/ginx.md).

## License

![licence]

`ginx` is open-source and available under the [LICENCE](LICENSE).

For more detailed usage, you can always use `ginx --help`.

[licence]: https://img.shields.io/github/license/didactiklabs/ginx
[downloads-badge]: https://img.shields.io/github/downloads/didactiklabs/ginx/total?logo=github&logoColor=white&style=flat-square
[releases]: https://github.com/didactiklabs/ginx/releases
[star]: https://img.shields.io/github/stars/didactiklabs/ginx
[version]: https://img.shields.io/github/v/release/didactiklabs/ginx
137 changes: 137 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package cmd

import (
"fmt"
"log"
"os"
"time"

"github.com/go-git/go-git/v5"
"github.com/spf13/cobra"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

"github.com/didactiklabs/ginx/internal/utils"
)

var (
versionFlag bool
version string
logLevelFlag string
sourceFlag string
branchFlag string
pollIntervalFlag int
)

var RootCmd = &cobra.Command{
Use: "ginx [flags] -- <command>",
Short: "ginx",
Long: `
Ginx is a cli tool that watch a remote repository and run an arbitrary command on changes/updates.
`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Initialize configuration here
if versionFlag {
fmt.Printf("%s", version)
} else {
initConfig()
}
},
Run: func(cmd *cobra.Command, args []string) {
var r *git.Repository
var err error
source := sourceFlag
branch := branchFlag
interval := time.Duration(pollIntervalFlag) * time.Second
dir, err := os.MkdirTemp("", "ginx-*")
if err != nil {
utils.Logger.Fatal("Failed to create temporary directory.", zap.Error(err))
}

if !utils.IsRepoCloned(source) {
utils.Logger.Info("Cloning repository.", zap.String("url", source), zap.String("branch", branch))
r, err = utils.CloneRepo(source, branch, dir)
if err != nil {
utils.Logger.Fatal("Failed to clone repository.", zap.Error(err))
}
} else {
r, err = git.PlainOpen(dir)
utils.Logger.Info("Repository already exist, open directory repository.", zap.String("directory", dir))
if err != nil {
utils.Logger.Fatal("Failed to open existing directory repository.", zap.Error(err))
}
}

log.Println("Starting remote repository watcher...")
for {
// Get the latest commit hash from the remote repository
remoteCommit, err := utils.GetLatestRemoteCommit(r, branch)
utils.Logger.Debug("Fetched remote commit.", zap.String("remoteCommit", remoteCommit))
if err != nil {
utils.Logger.Fatal("error fetching local commit.", zap.Error(err))
}

// Get the latest commit hash from the local repository
localCommit, err := utils.GetLatestLocalCommit(dir)
utils.Logger.Debug("Fetched local commit.", zap.String("localCommit", localCommit))
if err != nil {
utils.Logger.Fatal("error fetching local commit.", zap.Error(err))
}

if remoteCommit != localCommit {
log.Println("Detected remote changes. Pulling for latest changes...")
if err := utils.PullRepo(r); err != nil {
utils.Logger.Info("Failed to pull. Recloning repository.", zap.String("url", source))
err := os.RemoveAll(dir)
if err != nil {
utils.Logger.Fatal("error removing directory.", zap.Error(err))
}
_, err = utils.CloneRepo(source, branch, dir)
if err != nil {
utils.Logger.Fatal("Failed to clone repository.", zap.Error(err))
}
}
if len(args) > 0 {
utils.Logger.Info("Running command.", zap.String("command", args[0]), zap.Any("args", args[1:]))
if err := utils.RunCommand(dir, args[0], args[1:]...); err != nil {
utils.Logger.Error("Failed to run command.", zap.Error(err))
}
}
} else {
utils.Logger.Info("No changes detected in remote repository.", zap.String("url", source))
}
time.Sleep(interval)
}
},
Args: cobra.ArbitraryArgs,
}

func initConfig() {
// Your configuration initialization logic
logLevel := zapcore.InfoLevel //nolint:all
switch logLevelFlag {
case "debug":
logLevel = zapcore.DebugLevel
case "error":
logLevel = zapcore.ErrorLevel
default:
logLevel = zapcore.InfoLevel
}
utils.InitializeLogger(logLevel)
utils.Logger.Info("Initialized configuration.")
}

func Execute() {
err := RootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
RootCmd.Flags().BoolVarP(&versionFlag, "version", "v", false, "display version information")
RootCmd.PersistentFlags().StringVarP(&logLevelFlag, "log-level", "l", "info", "override log level (debug, info, error)")
RootCmd.PersistentFlags().StringVarP(&sourceFlag, "source", "s", "", "git repository to watch")
RootCmd.PersistentFlags().StringVarP(&branchFlag, "branch", "b", "main", "branch to watch")
RootCmd.PersistentFlags().IntVarP(&pollIntervalFlag, "interval", "n", 30, "interval in seconds to poll the remote repo")
}
26 changes: 26 additions & 0 deletions docs/ginx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## ginx

ginx

### Synopsis


Ginx is a cli tool that watch a remote repository and run an arbitrary command on changes/updates.


```
ginx [flags] -- <command>
```

### Options

```
-b, --branch string branch to watch (default "main")
-h, --help help for ginx
-n, --interval int interval in seconds to poll the remote repo (default 30)
-l, --log-level string override log level (debug, info, error) (default "info")
-s, --source string git repository to watch
-v, --version display version information
```

###### Auto generated by spf13/cobra on 22-Dec-2024
Loading

0 comments on commit 2bd85e2

Please sign in to comment.