Skip to content

Commit e17b741

Browse files
lieut-datamickmister
authored andcommitted
Sync with playbooks: install-go-tools, gotestsum, and dynamic versions (mattermost-community#192)
* Revert "Update main.go (mattermost-community#154)" This reverts commit be4a281d0cc791d10e6e5ae917b325b2f054e475. * Revert "[MM-33506] Use embed package to include plugin manifest (mattermost-community#145)" This reverts commit ca9ee3c17c6920a636a33f378e17395afd6f329f. * Revert "Don't generate manifest.ts (mattermost-community#127)" This reverts commit 18d30b50bc7ba800c9f05bfd82970781db0aea3e. * install-go-tools target, adopt gotestsum * bring back make apply + automatic versioning * Update build/manifest/main.go Co-authored-by: Michael Kochell <[email protected]> * suppress git describe error when no tags match * make version/release notes opt-in * fix whitespace in Makefile * document version management options --------- Co-authored-by: Michael Kochell <[email protected]>
1 parent f337d1b commit e17b741

File tree

9 files changed

+191
-33
lines changed

9 files changed

+191
-33
lines changed

.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
server/manifest.go linguist-generated=true

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
dist
2+
server/manifest.go

Makefile

+38-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ GO ?= $(shell command -v go 2> /dev/null)
22
NPM ?= $(shell command -v npm 2> /dev/null)
33
CURL ?= $(shell command -v curl 2> /dev/null)
44
MM_DEBUG ?=
5-
MANIFEST_FILE ?= plugin.json
65
GOPATH ?= $(shell go env GOPATH)
76
GO_TEST_FLAGS ?= -race
87
GO_BUILD_FLAGS ?=
@@ -13,6 +12,10 @@ DEFAULT_GOARCH := $(shell go env GOARCH)
1312

1413
export GO111MODULE=on
1514

15+
# We need to export GOBIN to allow it to be set
16+
# for processes spawned from the Makefile
17+
export GOBIN ?= $(PWD)/bin
18+
1619
# You can include assets this directory into the bundle. This can be e.g. used to include profile pictures.
1720
ASSETS_DIR ?= assets
1821

@@ -22,7 +25,6 @@ default: all
2225

2326
# Verify environment, and define PLUGIN_ID, PLUGIN_VERSION, HAS_SERVER and HAS_WEBAPP as needed.
2427
include build/setup.mk
25-
include build/legacy.mk
2628

2729
BUNDLE_NAME ?= $(PLUGIN_ID)-$(PLUGIN_VERSION).tar.gz
2830

@@ -41,24 +43,34 @@ endif
4143
.PHONY: all
4244
all: check-style test dist
4345

46+
## Propagates plugin manifest information into the server/ and webapp/ folders.
47+
.PHONY: apply
48+
apply:
49+
./build/bin/manifest apply
50+
51+
## Install go tools
52+
install-go-tools:
53+
@echo Installing go tools
54+
$(GO) install github.com/golangci/golangci-lint/cmd/[email protected]
55+
$(GO) install gotest.tools/[email protected]
56+
4457
## Runs eslint and golangci-lint
4558
.PHONY: check-style
46-
check-style: webapp/node_modules
59+
check-style: apply webapp/node_modules install-go-tools
4760
@echo Checking for style guide compliance
4861

4962
ifneq ($(HAS_WEBAPP),)
5063
cd webapp && npm run lint
5164
cd webapp && npm run check-types
5265
endif
5366

67+
# It's highly recommended to run go-vet first
68+
# to find potential compile errors that could introduce
69+
# weird reports at golangci-lint step
5470
ifneq ($(HAS_SERVER),)
55-
@if ! [ -x "$$(command -v golangci-lint)" ]; then \
56-
echo "golangci-lint is not installed. Please see https://github.com/golangci/golangci-lint#install for installation instructions."; \
57-
exit 1; \
58-
fi; \
59-
6071
@echo Running golangci-lint
61-
golangci-lint run ./...
72+
$(GO) vet ./...
73+
$(GOBIN)/golangci-lint run ./...
6274
endif
6375

6476
## Builds the server, if it exists, for all supported architectures, unless MM_SERVICESETTINGS_ENABLEDEVELOPER is set.
@@ -104,7 +116,7 @@ endif
104116
bundle:
105117
rm -rf dist/
106118
mkdir -p dist/$(PLUGIN_ID)
107-
cp $(MANIFEST_FILE) dist/$(PLUGIN_ID)/
119+
./build/bin/manifest dist
108120
ifneq ($(wildcard $(ASSETS_DIR)/.),)
109121
cp -r $(ASSETS_DIR) dist/$(PLUGIN_ID)/
110122
endif
@@ -125,7 +137,7 @@ endif
125137

126138
## Builds and bundles the plugin.
127139
.PHONY: dist
128-
dist: server webapp bundle
140+
dist: apply server webapp bundle
129141

130142
## Builds and installs the plugin to a server.
131143
.PHONY: deploy
@@ -134,7 +146,7 @@ deploy: dist
134146

135147
## Builds and installs the plugin to a server, updating the webapp automatically when changed.
136148
.PHONY: watch
137-
watch: server bundle
149+
watch: apply server bundle
138150
ifeq ($(MM_DEBUG),)
139151
cd webapp && $(NPM) run build:watch
140152
else
@@ -188,17 +200,28 @@ detach: setup-attach
188200

189201
## Runs any lints and unit tests defined for the server and webapp, if they exist.
190202
.PHONY: test
191-
test: webapp/node_modules
203+
test: apply webapp/node_modules install-go-tools
204+
ifneq ($(HAS_SERVER),)
205+
$(GOBIN)/gotestsum -- -v ./...
206+
endif
207+
ifneq ($(HAS_WEBAPP),)
208+
cd webapp && $(NPM) run test;
209+
endif
210+
211+
## Runs any lints and unit tests defined for the server and webapp, if they exist, optimized
212+
## for a CI environment.
213+
.PHONY: test-ci
214+
test-ci: apply webapp/node_modules install-go-tools
192215
ifneq ($(HAS_SERVER),)
193-
$(GO) test -v $(GO_TEST_FLAGS) ./server/...
216+
$(GOBIN)/gotestsum --format standard-verbose --junitfile report.xml -- ./...
194217
endif
195218
ifneq ($(HAS_WEBAPP),)
196219
cd webapp && $(NPM) run test;
197220
endif
198221

199222
## Creates a coverage report for the server code.
200223
.PHONY: coverage
201-
coverage: webapp/node_modules
224+
coverage: apply webapp/node_modules
202225
ifneq ($(HAS_SERVER),)
203226
$(GO) test $(GO_TEST_FLAGS) -coverprofile=server/coverage.txt ./server/...
204227
$(GO) tool cover -html=server/coverage.txt

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,12 @@ The `/autolink` commands allow the users to easily edit the configurations.
164164
## Development
165165

166166
This plugin contains a server portion. Read our documentation about the [Developer Workflow](https://developers.mattermost.com/integrate/plugins/developer-workflow/) and [Developer Setup](https://developers.mattermost.com/integrate/plugins/developer-setup/) for more information about developing and extending plugins.
167+
168+
### Releasing new versions
169+
170+
The version of a plugin is determined at compile time, automatically populating a `version` field in the [plugin manifest](plugin.json):
171+
* If the current commit matches a tag, the version will match after stripping any leading `v`, e.g. `1.3.1`.
172+
* Otherwise, the version will combine the nearest tag with `git rev-parse --short HEAD`, e.g. `1.3.1+d06e53e1`.
173+
* If there is no version tag, an empty version will be combined with the short hash, e.g. `0.0.0+76081421`.
174+
175+
To disable this behaviour, manually populate and maintain the `version` field.

build/legacy.mk

-3
This file was deleted.

build/manifest/main.go

+135
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,50 @@ import (
44
"encoding/json"
55
"fmt"
66
"os"
7+
"strings"
78

89
"github.com/mattermost/mattermost/server/public/model"
910
"github.com/pkg/errors"
1011
)
1112

13+
const pluginIDGoFileTemplate = `// This file is automatically generated. Do not modify it manually.
14+
15+
package main
16+
17+
import (
18+
"encoding/json"
19+
"strings"
20+
21+
"github.com/mattermost/mattermost/server/public/model"
22+
)
23+
24+
var manifest *model.Manifest
25+
26+
const manifestStr = ` + "`" + `
27+
%s
28+
` + "`" + `
29+
30+
func init() {
31+
_ = json.NewDecoder(strings.NewReader(manifestStr)).Decode(&manifest)
32+
}
33+
`
34+
35+
const pluginIDJSFileTemplate = `// This file is automatically generated. Do not modify it manually.
36+
37+
const manifest = JSON.parse(` + "`" + `
38+
%s
39+
` + "`" + `);
40+
41+
export default manifest;
42+
`
43+
44+
// These build-time vars are read from shell commands and populated in ../setup.mk
45+
var (
46+
BuildHashShort string
47+
BuildTagLatest string
48+
BuildTagCurrent string
49+
)
50+
1251
func main() {
1352
if len(os.Args) <= 1 {
1453
panic("no cmd specified")
@@ -37,6 +76,16 @@ func main() {
3776
fmt.Printf("true")
3877
}
3978

79+
case "apply":
80+
if err := applyManifest(manifest); err != nil {
81+
panic("failed to apply manifest: " + err.Error())
82+
}
83+
84+
case "dist":
85+
if err := distManifest(manifest); err != nil {
86+
panic("failed to write manifest to dist directory: " + err.Error())
87+
}
88+
4089
default:
4190
panic("unrecognized command: " + cmd)
4291
}
@@ -62,6 +111,32 @@ func findManifest() (*model.Manifest, error) {
62111
return nil, errors.Wrap(err, "failed to parse manifest")
63112
}
64113

114+
// If no version is listed in the manifest, generate one based on the state of the current
115+
// commit, and use the first version we find (to prevent causing errors)
116+
if manifest.Version == "" {
117+
var version string
118+
tags := strings.Fields(BuildTagCurrent)
119+
for _, t := range tags {
120+
if strings.HasPrefix(t, "v") {
121+
version = t
122+
break
123+
}
124+
}
125+
if version == "" {
126+
if BuildTagLatest != "" {
127+
version = BuildTagLatest + "+" + BuildHashShort
128+
} else {
129+
version = "v0.0.0+" + BuildHashShort
130+
}
131+
}
132+
manifest.Version = strings.TrimPrefix(version, "v")
133+
}
134+
135+
// If no release notes specified, generate one from the latest tag, if present.
136+
if manifest.ReleaseNotesURL == "" && BuildTagLatest != "" {
137+
manifest.ReleaseNotesURL = manifest.HomepageURL + "releases/tag/" + BuildTagLatest
138+
}
139+
65140
return &manifest, nil
66141
}
67142

@@ -74,3 +149,63 @@ func dumpPluginID(manifest *model.Manifest) {
74149
func dumpPluginVersion(manifest *model.Manifest) {
75150
fmt.Printf("%s", manifest.Version)
76151
}
152+
153+
// applyManifest propagates the plugin_id into the server and webapp folders, as necessary
154+
func applyManifest(manifest *model.Manifest) error {
155+
if manifest.HasServer() {
156+
// generate JSON representation of Manifest.
157+
manifestBytes, err := json.MarshalIndent(manifest, "", " ")
158+
if err != nil {
159+
return err
160+
}
161+
manifestStr := string(manifestBytes)
162+
163+
// write generated code to file by using Go file template.
164+
if err := os.WriteFile(
165+
"server/manifest.go",
166+
[]byte(fmt.Sprintf(pluginIDGoFileTemplate, manifestStr)),
167+
0600,
168+
); err != nil {
169+
return errors.Wrap(err, "failed to write server/manifest.go")
170+
}
171+
}
172+
173+
if manifest.HasWebapp() {
174+
// generate JSON representation of Manifest.
175+
// JSON is very similar and compatible with JS's object literals. so, what we do here
176+
// is actually JS code generation.
177+
manifestBytes, err := json.MarshalIndent(manifest, "", " ")
178+
if err != nil {
179+
return err
180+
}
181+
manifestStr := string(manifestBytes)
182+
183+
// Escape newlines
184+
manifestStr = strings.ReplaceAll(manifestStr, `\n`, `\\n`)
185+
186+
// write generated code to file by using JS file template.
187+
if err := os.WriteFile(
188+
"webapp/src/manifest.ts",
189+
[]byte(fmt.Sprintf(pluginIDJSFileTemplate, manifestStr)),
190+
0600,
191+
); err != nil {
192+
return errors.Wrap(err, "failed to open webapp/src/manifest.ts")
193+
}
194+
}
195+
196+
return nil
197+
}
198+
199+
// distManifest writes the manifest file to the dist directory
200+
func distManifest(manifest *model.Manifest) error {
201+
manifestBytes, err := json.MarshalIndent(manifest, "", " ")
202+
if err != nil {
203+
return err
204+
}
205+
206+
if err := os.WriteFile(fmt.Sprintf("dist/%s/plugin.json", manifest.Id), manifestBytes, 0600); err != nil {
207+
return errors.Wrap(err, "failed to write plugin.json")
208+
}
209+
210+
return nil
211+
}

build/setup.mk

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@ ifeq ($(GO),)
44
$(error "go is not available: see https://golang.org/doc/install")
55
endif
66

7+
# Gather build variables to inject into the manifest tool
8+
BUILD_HASH_SHORT = $(shell git rev-parse --short HEAD)
9+
BUILD_TAG_LATEST = $(shell git describe --tags --match 'v*' --abbrev=0 2>/dev/null)
10+
BUILD_TAG_CURRENT = $(shell git tag --points-at HEAD)
11+
712
# Ensure that the build tools are compiled. Go's caching makes this quick.
8-
$(shell cd build/manifest && $(GO) build -o ../bin/manifest)
13+
$(shell cd build/manifest && $(GO) build -ldflags '-X "main.BuildHashShort=$(BUILD_HASH_SHORT)" -X "main.BuildTagLatest=$(BUILD_TAG_LATEST)" -X "main.BuildTagCurrent=$(BUILD_TAG_CURRENT)"' -o ../bin/manifest)
914

1015
# Ensure that the deployment tools are compiled. Go's caching makes this quick.
1116
$(shell cd build/pluginctl && $(GO) build -o ../bin/pluginctl)

plugin.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
"description": "Automatically rewrite text matching a regular expression into a Markdown link.",
55
"homepage_url": "https://github.com/mattermost/mattermost-plugin-autolink",
66
"support_url": "https://github.com/mattermost/mattermost-plugin-autolink/issues",
7-
"release_notes_url": "https://github.com/mattermost/mattermost-plugin-autolink/releases/tag/v1.4.0",
87
"icon_path": "assets/icon.svg",
9-
"version": "1.4.0",
108
"min_server_version": "5.16.0",
119
"server": {
1210
"executables": {
@@ -19,7 +17,7 @@
1917
"executable": ""
2018
},
2119
"settings_schema": {
22-
"header": "Configure this plugin directly in the `config.json` file, or using the `/autolink` command. Learn more [in our documentation](https://github.com/mattermost/mattermost-plugin-autolink/blob/master/README.md).\n\n To report an issue, make a suggestion, or contribute, [check the plugin repository](https://github.com/mattermost/mattermost-plugin-autolink).",
20+
"header": "Configure this plugin directly in the config.json file, or using the /autolink command. Learn more [in our documentation](https://github.com/mattermost/mattermost-plugin-autolink/blob/master/README.md).\n\n To report an issue, make a suggestion, or contribute, [check the plugin repository](https://github.com/mattermost/mattermost-plugin-autolink).",
2321
"footer": "",
2422
"settings": [
2523
{

server/manifest.go

-11
This file was deleted.

0 commit comments

Comments
 (0)