Skip to content

Commit

Permalink
Sync with playbooks: install-go-tools, gotestsum, and dynamic versions (
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
2 people authored and ayusht2810 committed Feb 15, 2024
1 parent f337d1b commit e17b741
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
server/manifest.go linguist-generated=true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dist
server/manifest.go
53 changes: 38 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ GO ?= $(shell command -v go 2> /dev/null)
NPM ?= $(shell command -v npm 2> /dev/null)
CURL ?= $(shell command -v curl 2> /dev/null)
MM_DEBUG ?=
MANIFEST_FILE ?= plugin.json
GOPATH ?= $(shell go env GOPATH)
GO_TEST_FLAGS ?= -race
GO_BUILD_FLAGS ?=
Expand All @@ -13,6 +12,10 @@ DEFAULT_GOARCH := $(shell go env GOARCH)

export GO111MODULE=on

# We need to export GOBIN to allow it to be set
# for processes spawned from the Makefile
export GOBIN ?= $(PWD)/bin

# You can include assets this directory into the bundle. This can be e.g. used to include profile pictures.
ASSETS_DIR ?= assets

Expand All @@ -22,7 +25,6 @@ default: all

# Verify environment, and define PLUGIN_ID, PLUGIN_VERSION, HAS_SERVER and HAS_WEBAPP as needed.
include build/setup.mk
include build/legacy.mk

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

Expand All @@ -41,24 +43,34 @@ endif
.PHONY: all
all: check-style test dist

## Propagates plugin manifest information into the server/ and webapp/ folders.
.PHONY: apply
apply:
./build/bin/manifest apply

## Install go tools
install-go-tools:
@echo Installing go tools
$(GO) install github.com/golangci/golangci-lint/cmd/[email protected]
$(GO) install gotest.tools/[email protected]

## Runs eslint and golangci-lint
.PHONY: check-style
check-style: webapp/node_modules
check-style: apply webapp/node_modules install-go-tools
@echo Checking for style guide compliance

ifneq ($(HAS_WEBAPP),)
cd webapp && npm run lint
cd webapp && npm run check-types
endif

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

## Builds the server, if it exists, for all supported architectures, unless MM_SERVICESETTINGS_ENABLEDEVELOPER is set.
Expand Down Expand Up @@ -104,7 +116,7 @@ endif
bundle:
rm -rf dist/
mkdir -p dist/$(PLUGIN_ID)
cp $(MANIFEST_FILE) dist/$(PLUGIN_ID)/
./build/bin/manifest dist
ifneq ($(wildcard $(ASSETS_DIR)/.),)
cp -r $(ASSETS_DIR) dist/$(PLUGIN_ID)/
endif
Expand All @@ -125,7 +137,7 @@ endif

## Builds and bundles the plugin.
.PHONY: dist
dist: server webapp bundle
dist: apply server webapp bundle

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

## Builds and installs the plugin to a server, updating the webapp automatically when changed.
.PHONY: watch
watch: server bundle
watch: apply server bundle
ifeq ($(MM_DEBUG),)
cd webapp && $(NPM) run build:watch
else
Expand Down Expand Up @@ -188,17 +200,28 @@ detach: setup-attach

## Runs any lints and unit tests defined for the server and webapp, if they exist.
.PHONY: test
test: webapp/node_modules
test: apply webapp/node_modules install-go-tools
ifneq ($(HAS_SERVER),)
$(GOBIN)/gotestsum -- -v ./...
endif
ifneq ($(HAS_WEBAPP),)
cd webapp && $(NPM) run test;
endif

## Runs any lints and unit tests defined for the server and webapp, if they exist, optimized
## for a CI environment.
.PHONY: test-ci
test-ci: apply webapp/node_modules install-go-tools
ifneq ($(HAS_SERVER),)
$(GO) test -v $(GO_TEST_FLAGS) ./server/...
$(GOBIN)/gotestsum --format standard-verbose --junitfile report.xml -- ./...
endif
ifneq ($(HAS_WEBAPP),)
cd webapp && $(NPM) run test;
endif

## Creates a coverage report for the server code.
.PHONY: coverage
coverage: webapp/node_modules
coverage: apply webapp/node_modules
ifneq ($(HAS_SERVER),)
$(GO) test $(GO_TEST_FLAGS) -coverprofile=server/coverage.txt ./server/...
$(GO) tool cover -html=server/coverage.txt
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,12 @@ The `/autolink` commands allow the users to easily edit the configurations.
## Development

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.

### Releasing new versions

The version of a plugin is determined at compile time, automatically populating a `version` field in the [plugin manifest](plugin.json):
* If the current commit matches a tag, the version will match after stripping any leading `v`, e.g. `1.3.1`.
* Otherwise, the version will combine the nearest tag with `git rev-parse --short HEAD`, e.g. `1.3.1+d06e53e1`.
* If there is no version tag, an empty version will be combined with the short hash, e.g. `0.0.0+76081421`.

To disable this behaviour, manually populate and maintain the `version` field.
3 changes: 0 additions & 3 deletions build/legacy.mk

This file was deleted.

135 changes: 135 additions & 0 deletions build/manifest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,50 @@ import (
"encoding/json"
"fmt"
"os"
"strings"

"github.com/mattermost/mattermost/server/public/model"
"github.com/pkg/errors"
)

const pluginIDGoFileTemplate = `// This file is automatically generated. Do not modify it manually.
package main
import (
"encoding/json"
"strings"
"github.com/mattermost/mattermost/server/public/model"
)
var manifest *model.Manifest
const manifestStr = ` + "`" + `
%s
` + "`" + `
func init() {
_ = json.NewDecoder(strings.NewReader(manifestStr)).Decode(&manifest)
}
`

const pluginIDJSFileTemplate = `// This file is automatically generated. Do not modify it manually.
const manifest = JSON.parse(` + "`" + `
%s
` + "`" + `);
export default manifest;
`

// These build-time vars are read from shell commands and populated in ../setup.mk
var (
BuildHashShort string
BuildTagLatest string
BuildTagCurrent string
)

func main() {
if len(os.Args) <= 1 {
panic("no cmd specified")
Expand Down Expand Up @@ -37,6 +76,16 @@ func main() {
fmt.Printf("true")
}

case "apply":
if err := applyManifest(manifest); err != nil {
panic("failed to apply manifest: " + err.Error())
}

case "dist":
if err := distManifest(manifest); err != nil {
panic("failed to write manifest to dist directory: " + err.Error())
}

default:
panic("unrecognized command: " + cmd)
}
Expand All @@ -62,6 +111,32 @@ func findManifest() (*model.Manifest, error) {
return nil, errors.Wrap(err, "failed to parse manifest")
}

// If no version is listed in the manifest, generate one based on the state of the current
// commit, and use the first version we find (to prevent causing errors)
if manifest.Version == "" {
var version string
tags := strings.Fields(BuildTagCurrent)
for _, t := range tags {
if strings.HasPrefix(t, "v") {
version = t
break
}
}
if version == "" {
if BuildTagLatest != "" {
version = BuildTagLatest + "+" + BuildHashShort
} else {
version = "v0.0.0+" + BuildHashShort
}
}
manifest.Version = strings.TrimPrefix(version, "v")
}

// If no release notes specified, generate one from the latest tag, if present.
if manifest.ReleaseNotesURL == "" && BuildTagLatest != "" {
manifest.ReleaseNotesURL = manifest.HomepageURL + "releases/tag/" + BuildTagLatest
}

return &manifest, nil
}

Expand All @@ -74,3 +149,63 @@ func dumpPluginID(manifest *model.Manifest) {
func dumpPluginVersion(manifest *model.Manifest) {
fmt.Printf("%s", manifest.Version)
}

// applyManifest propagates the plugin_id into the server and webapp folders, as necessary
func applyManifest(manifest *model.Manifest) error {
if manifest.HasServer() {
// generate JSON representation of Manifest.
manifestBytes, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
return err
}
manifestStr := string(manifestBytes)

// write generated code to file by using Go file template.
if err := os.WriteFile(
"server/manifest.go",
[]byte(fmt.Sprintf(pluginIDGoFileTemplate, manifestStr)),
0600,
); err != nil {
return errors.Wrap(err, "failed to write server/manifest.go")
}
}

if manifest.HasWebapp() {
// generate JSON representation of Manifest.
// JSON is very similar and compatible with JS's object literals. so, what we do here
// is actually JS code generation.
manifestBytes, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
return err
}
manifestStr := string(manifestBytes)

// Escape newlines
manifestStr = strings.ReplaceAll(manifestStr, `\n`, `\\n`)

// write generated code to file by using JS file template.
if err := os.WriteFile(
"webapp/src/manifest.ts",
[]byte(fmt.Sprintf(pluginIDJSFileTemplate, manifestStr)),
0600,
); err != nil {
return errors.Wrap(err, "failed to open webapp/src/manifest.ts")
}
}

return nil
}

// distManifest writes the manifest file to the dist directory
func distManifest(manifest *model.Manifest) error {
manifestBytes, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
return err
}

if err := os.WriteFile(fmt.Sprintf("dist/%s/plugin.json", manifest.Id), manifestBytes, 0600); err != nil {
return errors.Wrap(err, "failed to write plugin.json")
}

return nil
}
7 changes: 6 additions & 1 deletion build/setup.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ ifeq ($(GO),)
$(error "go is not available: see https://golang.org/doc/install")
endif

# Gather build variables to inject into the manifest tool
BUILD_HASH_SHORT = $(shell git rev-parse --short HEAD)
BUILD_TAG_LATEST = $(shell git describe --tags --match 'v*' --abbrev=0 2>/dev/null)
BUILD_TAG_CURRENT = $(shell git tag --points-at HEAD)

# Ensure that the build tools are compiled. Go's caching makes this quick.
$(shell cd build/manifest && $(GO) build -o ../bin/manifest)
$(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)

# Ensure that the deployment tools are compiled. Go's caching makes this quick.
$(shell cd build/pluginctl && $(GO) build -o ../bin/pluginctl)
Expand Down
4 changes: 1 addition & 3 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
"description": "Automatically rewrite text matching a regular expression into a Markdown link.",
"homepage_url": "https://github.com/mattermost/mattermost-plugin-autolink",
"support_url": "https://github.com/mattermost/mattermost-plugin-autolink/issues",
"release_notes_url": "https://github.com/mattermost/mattermost-plugin-autolink/releases/tag/v1.4.0",
"icon_path": "assets/icon.svg",
"version": "1.4.0",
"min_server_version": "5.16.0",
"server": {
"executables": {
Expand All @@ -19,7 +17,7 @@
"executable": ""
},
"settings_schema": {
"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).",
"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).",
"footer": "",
"settings": [
{
Expand Down
11 changes: 0 additions & 11 deletions server/manifest.go

This file was deleted.

0 comments on commit e17b741

Please sign in to comment.