Skip to content

Commit 62d71da

Browse files
committed
Copy in source files from the hugoreleaser repo with some renames
1 parent feedf7a commit 62d71da

File tree

8 files changed

+326
-2
lines changed

8 files changed

+326
-2
lines changed

‎.github/workflows/test.yml‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
on:
2+
push:
3+
branches: [ main ]
4+
pull_request:
5+
name: Test
6+
jobs:
7+
test:
8+
strategy:
9+
matrix:
10+
go-version: [1.19.x]
11+
platform: [ macos-latest, ubuntu-latest, windows-latest]
12+
runs-on: ${{ matrix.platform }}
13+
steps:
14+
- name: Install Go
15+
uses: actions/setup-go@v3
16+
with:
17+
go-version: ${{ matrix.go-version }}
18+
- name: Install staticcheck
19+
run: go install honnef.co/go/tools/cmd/staticcheck@latest
20+
shell: bash
21+
- name: Update PATH
22+
run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
23+
shell: bash
24+
- name: Checkout code
25+
uses: actions/checkout@v1
26+
- name: Fmt
27+
if: matrix.platform != 'windows-latest' # :(
28+
run: "diff <(gofmt -d .) <(printf '')"
29+
shell: bash
30+
- name: Vet
31+
run: go vet ./...
32+
- name: Staticcheck
33+
run: staticcheck ./...
34+
- name: Test
35+
run: go test -race ./...

‎README.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
# hugoreleaser-plugins-api
2-
Plugins API for https://github.com/gohugoio/hugoreleaser
1+
[![Tests on Linux, MacOS and Windows](https://github.com/gohugoio/hugoreleaser-plugins-api/workflows/Test/badge.svg)](https://github.com/gohugoio/hugoreleaser-plugins-api/actions?query=workflow%3ATest)
2+
[![Go Report Card](https://goreportcard.com/badge/github.com/gohugoio/hugoreleaser-plugins-api)](https://goreportcard.com/report/github.com/gohugoio/hugoreleaser-plugins-api)
3+
[![GoDoc](https://godoc.org/github.com/gohugoio/hugoreleaser-plugins-api?status.svg)](https://godoc.org/github.com/gohugoio/hugoreleaser-plugins-api)
4+
5+
6+
Plugins API for https://github.com/gohugoio/hugoreleaser-plugins-api

‎archiveplugin/archiveplugin.go‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2022 The Hugoreleaser Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package archiveplugin
16+
17+
import (
18+
"fmt"
19+
20+
"github.com/gohugoio/hugoreleaser-plugins-api/model"
21+
)
22+
23+
const (
24+
// Version gets incremented on incompatible changes to the archive plugin or its runtime,
25+
// think of this as a major version increment in semver terms.
26+
// This should almost never happen, but if it does, the old archive plugin will probably not work as expected.
27+
// This will be detected on Hugoreleaser startup and the build will fail.
28+
// The plugin server then needs to be updated and re-tested.
29+
Version = 0
30+
)
31+
32+
var (
33+
_ model.Initializer = (*ArchiveFile)(nil)
34+
_ model.Initializer = (*Request)(nil)
35+
)
36+
37+
// Request is what is sent to an external archive tool.
38+
type Request struct {
39+
// Version is the archive plugin version.
40+
// This is just used for validation on startup.
41+
Version int `toml:"version"`
42+
43+
// Heartbeat is a string that is echoed back to the caller,
44+
// used to test that plugin servers are up and running.
45+
Heartbeat string `toml:"heartbeat"`
46+
47+
// BuildInfo holds the basic build information about the current build.
48+
BuildInfo model.BuildInfo `toml:"build_info"`
49+
50+
// Settings for the archive.
51+
// This is the content of archive_settings.custom_settings.
52+
Settings map[string]any `toml:"settings"`
53+
54+
Files []ArchiveFile `toml:"files"`
55+
56+
// Filename with extension.
57+
OutFilename string `toml:"out_filename"`
58+
}
59+
60+
// HeartbeatResponse returns a Response that, if the second return value is true,
61+
// will be returned to the caller.
62+
func (r Request) HeartbeatResponse() (Response, bool) {
63+
if r.Heartbeat == "" {
64+
return Response{}, false
65+
}
66+
var err *model.Error
67+
if r.Version != Version {
68+
err = &model.Error{Msg: fmt.Sprintf("archive plugin version mismatch: client sent %d, server is at %d", r.Version, Version)}
69+
}
70+
return Response{Heartbeat: r.Heartbeat, Error: err}, true
71+
}
72+
73+
func (r *Request) Init() error {
74+
what := "archive_request"
75+
if r.OutFilename == "" {
76+
return fmt.Errorf("%s: archive request has no output filename", what)
77+
}
78+
for i := range r.Files {
79+
f := &r.Files[i]
80+
if err := f.Init(); err != nil {
81+
return fmt.Errorf("%s: %v", what, err)
82+
}
83+
}
84+
return nil
85+
}
86+
87+
// Response is what is sent back from an external archive tool.
88+
type Response struct {
89+
// Heartbeat is a string that is echoed back to the caller,
90+
// used to test that plugin servers are up and running.
91+
Heartbeat string `toml:"heartbeat"`
92+
93+
Error *model.Error `toml:"err"`
94+
}
95+
96+
func (r Response) Err() error {
97+
if r.Error == nil {
98+
// Make sure that resp.Err() == nil.
99+
return nil
100+
}
101+
return r.Error
102+
}
103+
104+
type ArchiveFile struct {
105+
// The source filename.
106+
SourcePathAbs string `toml:"source_path_abs"`
107+
108+
// Relative target path, including the name of the file.
109+
TargetPath string `toml:"target_path"`
110+
}
111+
112+
func (a *ArchiveFile) Init() error {
113+
return nil
114+
}

‎go.mod‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module github.com/gohugoio/hugoreleaser-plugins-api
2+
3+
go 1.19
4+
5+
require (
6+
github.com/bep/execrpc v0.7.0
7+
github.com/mitchellh/mapstructure v1.5.0
8+
)
9+
10+
require (
11+
github.com/bep/helpers v0.1.0 // indirect
12+
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
13+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
14+
)

‎go.sum‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
github.com/bep/execrpc v0.7.0 h1:IZneJQielOC2sdHTz/wJTfBgEDxA7WHHMwL1q7d4yB0=
2+
github.com/bep/execrpc v0.7.0/go.mod h1:dhMMXFX/IfDRQrp4/EHqqYbYfHS53bF/9kiHIG/ChJw=
3+
github.com/bep/helpers v0.1.0 h1:HFLG+W6axHackmKMk0houEnz9G2aiBrDMZyOvL9J0WM=
4+
github.com/bep/helpers v0.1.0/go.mod h1:/QpHdmcPagDw7+RjkLFCvnlUc8lQ5kg4KDrEkb2Yyco=
5+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
6+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
8+
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
9+
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
10+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
11+
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
12+
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
13+
github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
14+
github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
15+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
16+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17+
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
18+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
19+
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
20+
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
21+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
22+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
23+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
24+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
25+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

‎model/helpers.go‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package model
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/mitchellh/mapstructure"
7+
)
8+
9+
// FromNMap converts m to T.
10+
// See https://pkg.go.dev/github.com/mitchellh/mapstructure#section-readme
11+
func FromMap[T any](m map[string]any) (T, error) {
12+
var t T
13+
err := mapstructure.WeakDecode(m, &t)
14+
return t, err
15+
}
16+
17+
// Error is an error that can be returned from a plugin,
18+
// it's main quality is that it can be marshalled to and from TOML/JSON etc.
19+
func NewError(what string, err error) *Error {
20+
return &Error{Msg: fmt.Sprintf("%s: %v", what, err)}
21+
}
22+
23+
// Error holds an error message.
24+
type Error struct {
25+
Msg string `toml:"msg"`
26+
}
27+
28+
func (r Error) Error() string {
29+
return r.Msg
30+
}

‎model/model.go‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2022 The Hugoreleaser Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package model
16+
17+
type Initializer interface {
18+
// Init initializes a config struct, that could be parsing of strings into Go objects, compiling of Glob patterns etc.
19+
// It returns an error if the initialization failed.
20+
Init() error
21+
}
22+
23+
// BuildInfo hold the core information about a build.
24+
// This is used both by the plugins and the built-in archive implementation
25+
// as the template context for the name template.
26+
// It's kept here in this package because it's convenient.
27+
type BuildInfo struct {
28+
Project string `toml:"project"`
29+
Tag string `toml:"tag"`
30+
Goos string `toml:"goos"`
31+
Goarch string `toml:"goarch"`
32+
}

‎server/server.go‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2022 The Hugoreleaser Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package server
16+
17+
import (
18+
"fmt"
19+
20+
"github.com/bep/execrpc"
21+
)
22+
23+
// StatusInfoLog is used to mark a INFO log message from the server.
24+
const StatusInfoLog = 101
25+
26+
type Server[Q, R any] struct {
27+
*execrpc.Server[Q, R]
28+
}
29+
30+
type Heartbeater[R any] interface {
31+
HeartbeatResponse() (R, bool)
32+
}
33+
34+
// New creates a new server which will call the given function with a request Q.
35+
// The Dispatcher an be used for logging. Any errors needs to be sent in R.
36+
func New[Q Heartbeater[R], R any](call func(Dispatcher, Q) R) (*Server[Q, R], error) {
37+
rpcServer, err := execrpc.NewServer(
38+
execrpc.ServerOptions[Q, R]{
39+
Call: func(d execrpc.Dispatcher, req Q) R {
40+
if r, ok := req.HeartbeatResponse(); ok {
41+
return r
42+
}
43+
return call(dispatcherAdapter{d}, req)
44+
},
45+
},
46+
)
47+
if err != nil {
48+
return nil, err
49+
}
50+
return &Server[Q, R]{
51+
Server: rpcServer,
52+
}, nil
53+
}
54+
55+
type dispatcherAdapter struct {
56+
execRpcDispatcher execrpc.Dispatcher
57+
}
58+
59+
func (d dispatcherAdapter) Infof(format string, args ...interface{}) {
60+
d.execRpcDispatcher.Send(execrpc.Message{
61+
Header: execrpc.Header{
62+
Status: StatusInfoLog,
63+
},
64+
Body: []byte(fmt.Sprintf(format, args...)),
65+
})
66+
}
67+
68+
type Dispatcher interface {
69+
Infof(format string, args ...interface{})
70+
}

0 commit comments

Comments
 (0)