Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
idodod committed Jan 20, 2022
0 parents commit 74fe4ef
Show file tree
Hide file tree
Showing 24 changed files with 1,007 additions and 0 deletions.
1 change: 1 addition & 0 deletions .earthignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cmd/tester/*
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true

- uses: nelonoel/[email protected]

- uses: earthly/actions/setup-earthly@v1
with:
version: v0.6.4

- name: Earthly Version
run: earthly --version

- name: Build
env:
COMMIT_HASH: ${{ github.sha }}
FORCE_COLOR: 1
run: earthly -P --ci +all
46 changes: 46 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Release

on:
push:
tags:
- 'v[0-9]+\.[0-9]+\.[0-9]+'

jobs:
release-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true

- uses: nelonoel/[email protected]

- uses: earthly/actions/setup-earthly@v1
with:
version: v0.6.4

- name: Earthly Version
run: earthly --version

- name: Create Version
id: version
if: success()
run: |
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
# set to output var
echo ::set-output name=VERSION::${VERSION}
- name: Build
if: success()
env:
FORCE_COLOR: 1
VERSION: ${{ steps.version.outputs.VERSION }}
run: earthly -P --ci --output +all --VERSION=$VERSION

- name: Upload Release Assets
if: success()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release upload $BRANCH_NAME ./bin/protoc-gen-fieldmask*.zip
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bin/
gen/
.idea/
vendor/
81 changes: 81 additions & 0 deletions Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
VERSION 0.6

ARG ALPINE_VERSION=3.15
ARG GO_VERSION=1.17
ARG LINTER_VERSION=v1.43.0
FROM golang:$GO_VERSION-alpine$ALPINE_VERSION
WORKDIR /app

stage:
COPY --dir go.mod go.sum ./
RUN go mod download -x
COPY --dir protoc cmd .
SAVE ARTIFACT /app

vendor:
FROM +stage
RUN go mod vendor

lint:
# Installs golangci-lint to ./bin
RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s $LINTER_VERSION
COPY +stage/app .
RUN ./bin/golangci-lint run --skip-dirs=vendor --skip-dirs=./gen/ --deadline=5m --tests=true -E revive \
-E gosec -E unconvert -E goconst -E gocyclo -E goimports

build:
FROM +vendor
# compile app binary, save as artifact
ARG VERSION="dev"
ARG GOOS
ARG GOARCH
RUN go build -ldflags="-s -w -X 'main.version=${VERSION}'" -mod=vendor -o bin/protoc-gen-fieldmask ./cmd/protoc-gen-fieldmask/...
SAVE ARTIFACT ./bin/protoc-gen-fieldmask /protoc-gen-fieldmask

zip:
RUN apk add zip
WORKDIR /artifacts
ARG VERSION
ARG ZIP_FILE_NAME
ARG EXT
COPY (+build/protoc-gen-fieldmask) protoc-gen-fieldmask${EXT}
RUN zip -m protoc-gen-fieldmask-${VERSION}-${ZIP_FILE_NAME}.zip protoc-gen-fieldmask${EXT}
SAVE ARTIFACT /artifacts

build-all:
WORKDIR /artifacts
COPY (+zip/artifacts/*.zip --GOOS=darwin --GOARCH=amd64 --ZIP_FILE_NAME=osx-x86_64) .
COPY (+zip/artifacts/*.zip --GOOS=linux --GOARCH=386 --ZIP_FILE_NAME=linux-x86_32) .
COPY (+zip/artifacts/*.zip --GOOS=linux --GOARCH=amd64 --ZIP_FILE_NAME=linux-x86_64) .
COPY (+zip/artifacts/*.zip --GOOS=windows --GOARCH=386 --ZIP_FILE_NAME=win32 --EXT=.exe) .
COPY (+zip/artifacts/*.zip --GOOS=windows --GOARCH=amd64 --ZIP_FILE_NAME=win64 --EXT=.exe) .
SAVE ARTIFACT /artifacts AS LOCAL bin

test-gen:
ARG DOCKER_PROTOC_VERSION=1.42_0
FROM namely/protoc-all:$DOCKER_PROTOC_VERSION
RUN mkdir /plugins
COPY +build/protoc-gen-fieldmask /usr/local/bin/.
COPY --dir protos .
RUN entrypoint.sh -i protos -d protos/cases -l go -o gen
RUN entrypoint.sh -i protos -d protos/cases/thirdpartyimport -l go -o gen
RUN protoc -I/opt/include -Iprotos --fieldmask_out=gen protos/cases/*.proto protos/cases/thirdpartyimport/*.proto
SAVE ARTIFACT gen /gen AS LOCAL test/gen

test:
FROM +vendor
RUN apk add build-base
COPY --dir test .
COPY --dir +test-gen/gen test/.
RUN go mod vendor
RUN go test github.com/idodod/protoc-gen-fieldmask/test

all:
BUILD +lint
BUILD +test
BUILD +build-all

clean:
LOCALLY
RUN rm -rf test/gen vendor

21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Ido David

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
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.
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# protoc-gen-fieldmask

[![CI](https://github.com/idodod/protoc-gen-fieldmask/actions/workflows/ci.yml/badge.svg)](https://github.com/idodod/protoc-gen-fieldmask/actions/workflows/ci.yml)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/idodod/protoc-gen-fieldmask)
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/idodod/protoc-gen-fieldmask)
![GitHub](https://img.shields.io/github/license/idodod/protoc-gen-fieldmask)

A protoc plugin that generates fieldmask paths as static type properties for proto messages, which elimantes the usage of error-prone strings.

For example, given the following proto messages:

```proto
syntax = "proto3";
package example;
option go_package = "example/;example";
import "google/type/date.proto";
message Foo {
string baz = 1;
int32 xyz = 2;
Bar my_bar = 3;
google.type.Date some_date = 4;
}
message Bar {
string some_field = 1;
bool another_field = 2;
}
```

fieldmasks paths can be used as follows:

```golang
foo := &example.Foo{}

# Prints "baz"
fmt.Println(foo.FieldMaskPaths().Baz())

# Prints "xyz"
fmt.Println(foo.FieldMaskPaths().Xyz())

# prints "my_bar"
fmt.Println(foo.FieldMaskPaths().MyBar().String())

# since baz is a nested message, we can print a nested path - "my_bar.some_field"
fmt.Println(foo.FieldMaskPaths().MyBar().SomeField())

# thirdparty messages work the same way:
#print "some_date"
fmt.Println(foo.FieldMaskPaths().SomeDate().String())

#print "some_date.year"
fmt.Println(foo.FieldMaskPaths().SomeDate().Year())
```

## Usage

### Installation

The plugin can be downloaded from the [release page](https://github.com/idodod/protoc-gen-fieldmask/releases/latest), and should be ideally installed somewhere available in your `$PATH`.

### Executing the plugin

```sh
protoc --fieldmask_out=gen protos/example.proto

# if the plugin is not in your $PATH:
protoc --fieldmask_out=out_dir protos/example.proto --plugin=protoc-gen-fieldmask=/path/to/protoc-gen-fieldmask
```

### Parameters

The following parameters can be set by passing `--fieldmask_opt` to the command:

* `maxdepth`: This option is relevant for a recursive message case.\
Specify the max depth for which the paths will be pregenerated. If the path depth gets over the max value, it will be generated at runtime.
default value is `7`.

## Features

* Currently the only supported language is `go`.
* All paths are pregenerated (except for recursive messages past `maxdepth`).
* Support all type of fields including repeated fields, maps, oneofs, third parties, nested messages and recursive messages.
45 changes: 45 additions & 0 deletions cmd/protoc-gen-fieldmask/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"errors"
"flag"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/idodod/protoc-gen-fieldmask/protoc"
"google.golang.org/protobuf/compiler/protogen"
)

const (
defaultMaxDepth = 7
defaultLang = "go"
)

var version = "dev"

func main() {
app := filepath.Base(os.Args[0])
showVersion := flag.Bool("version", false, "print the version and exit")
flag.Parse()
if *showVersion {
fmt.Printf("%s %v\n", app, version)
return
}

var flags flag.FlagSet
maxDepth := flags.Uint("maxdepth", defaultMaxDepth, "")
lang := flags.String("lang", defaultLang, "")
protogen.Options{
ParamFunc: flags.Set,
}.Run(func(plugin *protogen.Plugin) error {
if strings.ToLower(*lang) != defaultLang {
return errors.New("go is the only supported language at the moment")
}
if *maxDepth <= 0 {
return errors.New("maxdepth must be bigger than 0")
}
return protoc.Generate(plugin, *maxDepth)
})
}
16 changes: 16 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/idodod/protoc-gen-fieldmask

go 1.17

require (
github.com/iancoleman/strcase v0.2.0
github.com/stretchr/testify v1.7.0
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5
google.golang.org/protobuf v1.27.1
)

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
Loading

0 comments on commit 74fe4ef

Please sign in to comment.