diff --git a/.circleci/config.yml b/.circleci/config.yml index b00a076736..53ecc6dd51 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -109,6 +109,23 @@ jobs: make app-layers if [[ -n $(git status --porcelain) ]]; then echo "Please update the app layers using make app-layers"; exit 1; fi + build-api-spec: + docker: + - image: circleci/node:lts + working_directory: ~/mattermost + steps: + - attach_workspace: + at: ~/mattermost/ + - run: + command: | + git clone https://github.com/mattermost/mattermost-api-reference.git + cd mattermost-api-reference + make build + - persist_to_workspace: + root: ~/mattermost + paths: + - mattermost-api-reference + build: docker: - image: mattermost/mattermost-build-server:20200322_golang-1.14.1 @@ -127,7 +144,7 @@ jobs: export PATH=$PATH:$GOBIN cd mattermost-server make config-reset - make check-style BUILD_NUMBER='${CIRCLE_BRANCH}-${CIRCLE_BUILD_NUM}' MM_NO_ENTERPRISE_LINT=true + make check-style BUILD_NUMBER='${CIRCLE_BRANCH}-${CIRCLE_BUILD_NUM}' MM_NO_ENTERPRISE_LINT=true MM_VET_OPENSPEC_PATH='${PWD}/../mattermost-api-reference/v4/html/static/mattermost-openapi-v4.yaml' make build BUILD_NUMBER='${CIRCLE_BRANCH}-${CIRCLE_BUILD_NUM}' make package BUILD_NUMBER='${CIRCLE_BRANCH}-${CIRCLE_BUILD_NUM}' - store_artifacts: @@ -389,9 +406,13 @@ workflows: - check-app-layers: requires: - setup + - build-api-spec: + requires: + - setup - build: requires: - check-app-layers + - build-api-spec - upload-s3-sha: context: mattermost-ci-pr-builds-s3 requires: diff --git a/Makefile b/Makefile index 44007ae7ca..685d4ff5c0 100644 --- a/Makefile +++ b/Makefile @@ -517,9 +517,14 @@ vet: ## Run mattermost go vet specific checks @if ! [ -x "$$(command -v $(GOBIN)/mattermost-govet)" ]; then \ echo "mattermost-govet is not installed. Please install it executing \"GO111MODULE=off GOBIN=$(PWD)/bin go get -u github.com/mattermost/mattermost-govet\""; \ exit 1; \ + fi; + @VET_CMD="-license -structuredLogging -inconsistentReceiverName -tFatal"; \ + if ! [ -z "${MM_VET_OPENSPEC_PATH}" ] && [ -f "${MM_VET_OPENSPEC_PATH}" ]; then \ + VET_CMD="$$VET_CMD -openApiSync -openApiSync.spec=$$MM_VET_OPENSPEC_PATH"; \ + else \ + echo "MM_VET_OPENSPEC_PATH not set or spec yaml path in it is incorrect. Skipping API check"; \ fi; \ - - $(GO) vet -vettool=$(GOBIN)/mattermost-govet -license -structuredLogging -inconsistentReceiverName -tFatal ./... + $(GO) vet -vettool=$(GOBIN)/mattermost-govet $$VET_CMD ./... ifeq ($(BUILD_ENTERPRISE_READY),true) ifneq ($(MM_NO_ENTERPRISE_LINT),true) $(GO) vet -vettool=$(GOBIN)/mattermost-govet -enterpriseLicense -structuredLogging -tFatal ./enterprise/... diff --git a/api4/api.go b/api4/api.go index 20748c5ce6..26acf42383 100644 --- a/api4/api.go +++ b/api4/api.go @@ -21,8 +21,8 @@ type Routes struct { Users *mux.Router // 'api/v4/users' User *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}' - UserByUsername *mux.Router // 'api/v4/users/username/{username:[A-Za-z0-9_-\.]+}' - UserByEmail *mux.Router // 'api/v4/users/email/{email}' + UserByUsername *mux.Router // 'api/v4/users/username/{username:[A-Za-z0-9\\_\\-\\.]+}' + UserByEmail *mux.Router // 'api/v4/users/email/{email:.+}' Bots *mux.Router // 'api/v4/bots' Bot *mux.Router // 'api/v4/bots/{bot_user_id:[A-Za-z0-9]+}' @@ -32,8 +32,8 @@ type Routes struct { Team *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}' TeamForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}' TeamByName *mux.Router // 'api/v4/teams/name/{team_name:[A-Za-z0-9_-]+}' - TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members' - TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members/{user_id:[A-Za-z0-9_-]+}' + TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/members' + TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/members/{user_id:[A-Za-z0-9]+}' TeamMembersForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/members' Channels *mux.Router // 'api/v4/channels' @@ -57,9 +57,9 @@ type Routes struct { File *mux.Router // 'api/v4/files/{file_id:[A-Za-z0-9]+}' Plugins *mux.Router // 'api/v4/plugins' - Plugin *mux.Router // 'api/v4/plugins/{plugin_id:[A-Za-z0-9_-]+}' + Plugin *mux.Router // 'api/v4/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}' - PublicFile *mux.Router // 'files/{file_id:[A-Za-z0-9]+}/public' + PublicFile *mux.Router // '/files/{file_id:[A-Za-z0-9]+}/public' Commands *mux.Router // 'api/v4/commands' Command *mux.Router // 'api/v4/commands/{command_id:[A-Za-z0-9]+}' @@ -107,11 +107,11 @@ type Routes struct { Emojis *mux.Router // 'api/v4/emoji' Emoji *mux.Router // 'api/v4/emoji/{emoji_id:[A-Za-z0-9]+}' - EmojiByName *mux.Router // 'api/v4/emoji/name/{emoji_name:[A-Za-z0-9_-\.]+}' + EmojiByName *mux.Router // 'api/v4/emoji/name/{emoji_name:[A-Za-z0-9\\_\\-\\+]+}' - ReactionByNameForPostForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/posts/{post_id:[A-Za-z0-9]+}/reactions/{emoji_name:[A-Za-z0-9_-+]+}' + ReactionByNameForPostForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/posts/{post_id:[A-Za-z0-9]+}/reactions/{emoji_name:[A-Za-z0-9\\_\\-\\+]+}' - TermsOfService *mux.Router // 'api/v4/terms_of_service + TermsOfService *mux.Router // 'api/v4/terms_of_service' Groups *mux.Router // 'api/v4/groups' }