Skip to content

Commit

Permalink
Merge pull request #9 from luissimas/feature/ci
Browse files Browse the repository at this point in the history
Feature/ci
  • Loading branch information
luissimas authored Jun 21, 2024
2 parents bc7f2cd + 00aa62b commit d35bbca
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 11 deletions.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bin
docs
examples
.gitignore
.git/
**/*.md
Dockerfile
Makefile
10 changes: 10 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
87 changes: 87 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Check

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_call:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
format:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Format
run: go fmt ./... && git diff --exit-code
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Vet
run: go vet ./...
- name: Lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.58
module:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Mod tidy
run: go mod tidy && git diff --exit-code
- name: Mod download
run: go mod download
- name: Mod verify
run: go mod verify
build:
needs: [format, lint, module]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Build
run: go build -o /dev/null
test:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Test
run: go test -v -race -shuffle=on -coverprofile=coverage.txt ./...
- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage.txt
66 changes: 66 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Release

on:
push:
tags:
- "v*.*.*"

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
check:
uses: ./.github/workflows/check.yaml
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the container registry
uses: docker/login-action@v5
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
create-release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
- name: Run goreleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: '~> v2'
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
bin
dist/
46 changes: 46 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com

# The lines below are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/need to use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

version: 2

before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
- go generate ./...

builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin

archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_
{{- 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

changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM golang:1.22 AS build-stage

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -o /zettelkasten-exporter

FROM gcr.io/distroless/base-debian12 AS release-stage

WORKDIR /

COPY --from=build-stage /zettelkasten-exporter /zettelkasten-exporter

USER nonroot:nonroot

ENTRYPOINT ["/zettelkasten-exporter"]
23 changes: 19 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
BINARY_NAME=zettelkasten-exporter

.PHONY: all clean format test build run
.PHONY: all clean format vet lint test build run

all: format vet build
all: format vet build test

clean:
go clean
Expand All @@ -14,11 +14,26 @@ format:
vet:
go vet ./...

lint:
golangci-lint run

test:
go test ./...

build:
go build -o bin/$(BINARY_NAME) ./cmd/zettelkasten-exporter/main.go
go build -o bin/$(BINARY_NAME)

run: build
ZETTELKASTEN_DIRECTORY=./sample ./bin/$(BINARY_NAME)
LOG_LEVEL=INFO \
ZETTELKASTEN_GIT_URL=<GIT_URL> \
ZETTELKASTEN_GIT_BRANCH=master \
ZETTELKASTEN_GIT_TOKEN=<GIT_TOKEN> \
COLLECTION_INTERVAL=10s \
INFLUXDB_TOKEN=<INFLUXDB_TOKEN> \
INFLUXDB_URL=http://localhost:8086 \
INFLUXDB_ORG=default \
INFLUXDB_BUCKET=zettelkasten \
./bin/$(BINARY_NAME)

docker:
docker build . -t zettelkasten-exporter:latest
5 changes: 5 additions & 0 deletions internal/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ func (c *Collector) collectMetrics(root fs.FS) (metrics.Metrics, error) {
notes := make(map[string]metrics.NoteMetrics)

err := fs.WalkDir(root, ".", func(path string, dir fs.DirEntry, err error) error {
if err != nil {
slog.Error("Error on path. Will not enter it", slog.Any("error", err), slog.String("path", path))
return nil
}

// Skip ignored files or directories
if slices.Contains(c.config.IgnorePatterns, filepath.Base(path)) {
if dir.IsDir() {
Expand Down
5 changes: 4 additions & 1 deletion internal/collector/note.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func collectLinks(content []byte) map[string]int {
reader := text.NewReader(content)
root := md.Parser().Parse(reader)
links := make(map[string]int)
ast.Walk(root, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
err := ast.Walk(root, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering && slices.Contains(linkKinds, n.Kind()) {
var target string
switch v := n.(type) {
Expand All @@ -55,6 +55,9 @@ func collectLinks(content []byte) map[string]int {
}
return ast.WalkContinue, nil
})
if err != nil {
slog.Error("Error walking note AST", slog.Any("error", err))
}
slog.Debug("Collected links", slog.Any("links", links))
return links
}
17 changes: 13 additions & 4 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

type Config struct {
ZettelkastenDirectory string `koanf:"zettelkasten_directory" validate:"requiredWithout:ZettelkastenGitURL"`
ZettelkastenGitURL string `koanf:"zettelkasten_git_url" validate:"requiredWithout:ZettelkastenDirectory" validate:"url/isURL"`
ZettelkastenGitURL string `koanf:"zettelkasten_git_url" validate:"requiredWithout:ZettelkastenDirectory|url"`
ZettelkastenGitBranch string `koanf:"zettelkasten_git_branch"`
ZettelkastenGitToken string `koanf:"zettelkasten_git_token"`
LogLevel slog.Level `koanf:"log_level"`
Expand All @@ -32,16 +32,19 @@ func LoadConfig() (Config, error) {
k := koanf.New(".")

// Set default values
k.Load(structs.Provider(Config{
err := k.Load(structs.Provider(Config{
LogLevel: slog.LevelInfo,
IgnoreFiles: []string{".git", ".obsidian", ".trash", "README.md"},
ZettelkastenGitBranch: "main",
CollectionInterval: time.Minute * 5,
CollectHistoricalMetrics: true,
}, "koanf"), nil)
if err != nil {
return Config{}, fmt.Errorf("error loading default config values: %w", err)
}

// Load env variables
k.Load(env.ProviderWithValue("", ".", func(key, value string) (string, interface{}) {
err = k.Load(env.ProviderWithValue("", ".", func(key, value string) (string, interface{}) {
key = strings.ToLower(key)
if key == "collection_interval" {
parsedValue, err := parseCollectionInterval(value)
Expand All @@ -53,10 +56,16 @@ func LoadConfig() (Config, error) {
}
return key, value
}), nil)
if err != nil {
return Config{}, fmt.Errorf("error loading env variables: %w", err)
}

// Unmarshal into config struct
var cfg Config
k.Unmarshal("", &cfg)
err = k.Unmarshal("", &cfg)
if err != nil {
return Config{}, fmt.Errorf("error unmarshalling config: %w", err)
}

// Validate config
v := validate.Struct(cfg)
Expand Down
2 changes: 1 addition & 1 deletion internal/zettelkasten/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (g GitZettelkasten) WalkHistory(walkFunc WalkFunc) error {
return nil
})
err = w.Reset(&git.ResetOptions{
Commit: *&originalHash,
Commit: originalHash,
Mode: git.HardReset,
})
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion cmd/zettelkasten-exporter/main.go → main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import (
func main() {
// Setup
cfg, err := config.LoadConfig()
slog.SetLogLoggerLevel(cfg.LogLevel)
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: cfg.LogLevel}))
slog.SetDefault(logger)
if err != nil {
slog.Error("Error loading config", slog.Any("error", err))
os.Exit(1)
Expand Down

0 comments on commit d35bbca

Please sign in to comment.