Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 112 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
EXCLUDE_ENTERPRISE: true
GO_VERSION: 1.24.6

jobs:
webapp-test:
Expand Down Expand Up @@ -38,14 +39,118 @@ jobs:
run: cd focalboard; make webapp-ci

- name: set up golangci-lint
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.8
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.1.6

- name: Lint & test server
run: cd focalboard; make server-ci

dist:
uses: mattermost/actions-workflows/.github/workflows/plugin-dist-pr.yml@main
secrets: inherit
with:
dist-target: "dist-linux"
s3-prefix: "mattermost-plugin-boards"
runs-on: ubuntu-22.04
needs:
- webapp-test
permissions:
id-token: write
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: "focalboard"
fetch-depth: "0"

- name: Set up Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: "${{ env.GO_VERSION }}"
cache: true

- name: Setup Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version-file: focalboard/.nvmrc
cache: "npm"
cache-dependency-path: focalboard/webapp/package-lock.json

- name: Cache webapp node modules
id: cache-webapp-node-modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: focalboard/webapp/node_modules
key: ${{ runner.os }}-webapp-node-modules-${{ hashFiles('focalboard/webapp/package-lock.json') }}
restore-keys: ${{ runner.os }}-webapp-node-modules-

- name: Setup webapp npm deps
if: steps.cache-webapp-node-modules.outputs.cache-hit != 'true'
env:
NODE_ENV: development
run: |
cd focalboard/webapp
npm install --ignore-scripts --no-save

- name: ci/setup-chainctl
uses: chainguard-dev/setup-chainctl@v0.3.2
with:
identity: ${{ secrets.CHAINGUARD_IDENTITY }}

- name: ci/setup-build-tools
run: |
echo "Setting up build tools..."
cd focalboard
mkdir -p build/bin
cd build/manifest && go build -o ../bin/manifest
cd ../pluginctl && go build -o ../bin/pluginctl

- name: Build both distributions
env:
GO_VERSION: ${{ env.GO_VERSION }}
run: cd focalboard; make dist-all

- name: ci/display-signing-parameters
if: github.event_name == 'pull_request'
run: |
cd focalboard
echo "πŸ“¦ Plugin Artifact Signing Parameters"
echo "===================================="

# Extract plugin version using manifest tool (handles git versioning)
PLUGIN_VERSION=$(build/bin/manifest version)
# Add 'v' prefix for consistency with other plugin packages
if [[ ! $PLUGIN_VERSION == v* ]]; then
PLUGIN_VERSION="v${PLUGIN_VERSION}"
fi
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)

echo ""
echo "To sign artifacts from this PR, run the following command:"
echo ""
echo "gh workflow run sign-plugin-pr-artifacts.yaml \\"
echo " --repo mattermost/delivery-platform \\"
echo " --field repository_full_name=\"${{ github.repository }}\" \\"
echo " --field pr_number=\"${{ github.event.number }}\" \\"
echo " --field commit_sha=\"${{ github.sha }}\" \\"
echo " --field run_id=\"${{ github.run_id }}\" \\"
echo " --field plugin_version=\"${PLUGIN_VERSION}\" \\"
echo " --field include_fips=true"
echo ""
echo "Or use the GitHub web interface with these values:"
echo "- Repository Full Name: ${{ github.repository }}"
echo "- PR Number: ${{ github.event.number }}"
echo "- Commit SHA: ${{ github.sha }}"
echo "- Run ID: ${{ github.run_id }}"
echo "- Plugin Version: ${PLUGIN_VERSION}"
echo "- Include FIPS: true"
echo ""
echo "Expected artifact naming:"
echo "- mattermost-plugin-boards-${PLUGIN_VERSION}+${SHORT_SHA}-linux-amd64.tar.gz"
echo "- mattermost-plugin-boards-${PLUGIN_VERSION}+${SHORT_SHA}-fips-linux-amd64.tar.gz"
echo ""
echo "Artifacts will be available at:"
echo "https://plugins.releases.mattermost.com/pr/mattermost-plugin-boards/pr-${{ github.event.number }}-${SHORT_SHA}/"

- name: Upload all artifacts
uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.5.0
with:
name: all-plugin-artifacts
path: |
focalboard/dist/*.tar.gz
focalboard/dist-fips/*.tar.gz
retention-days: 7
2 changes: 1 addition & 1 deletion .github/workflows/lint-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
with:
go-version-file: focalboard/go.mod
- name: set up golangci-lint
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.8
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.1.6
- name: lint
run: |
cd focalboard
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ webapp/node_modules
webapp/dist
webapp/pack
dist
dist-fips
.build-cache/
package
bin
debug
Expand Down
175 changes: 141 additions & 34 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: prebuild clean cleanall ci server server-linux server-mac server-win server-linux-package generate watch-server webapp mac-app win-app-wpf linux-app modd-precheck templates-archive
.PHONY: prebuild clean cleanall ci server server-mac server-linux server-win server-linux-package generate watch-server webapp mac-app win-app-wpf linux-app modd-precheck templates-archive dist-all

PACKAGE_FOLDER = focalboard

Expand Down Expand Up @@ -38,7 +38,14 @@ MATTERMOST_PLUGINS_PATH=$(MM_SERVER_PATH)/plugins
BOARD_PLUGIN_PATH=$(MATTERMOST_PLUGINS_PATH)/boards
PLUGIN_NAME=boards

export GO111MODULE=on
# FIPS Support - similar to mattermost server
# To build FIPS-compliant plugin: make dist-fips
# Requires Docker to be installed and running
FIPS_IMAGE ?= cgr.dev/mattermost.com/go-msft-fips:1.24.6@sha256:b94d424ab26b590163634001b22242ceac6f5d76bfbbaa77b6f0dda97220c717

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

ASSETS_DIR ?= assets

Expand All @@ -51,7 +58,15 @@ default: all
# Verify environment, and define PLUGIN_ID, PLUGIN_VERSION, HAS_SERVER and HAS_WEBAPP as needed.
include build/setup.mk

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

# Helper function to copy common bundle files
define copy_bundle_files
$(if $(wildcard LICENSE.txt),cp -r LICENSE.txt $(1)/$(PLUGIN_ID)/)
$(if $(wildcard NOTICE.txt),cp -r NOTICE.txt $(1)/$(PLUGIN_ID)/)
$(if $(wildcard $(ASSETS_DIR)/.),cp -r $(ASSETS_DIR) $(1)/$(PLUGIN_ID)/)
$(if $(HAS_PUBLIC),cp -r public $(1)/$(PLUGIN_ID)/public/)
endef

# Include custom makefile, if present
ifneq ($(wildcard build/custom.mk),)
Expand Down Expand Up @@ -114,6 +129,48 @@ else
endif
endif

## Builds the server with FIPS compliance using Docker (requires Docker)
.PHONY: server-fips
server-fips: templates-archive
ifneq ($(HAS_SERVER),)
@echo Building FIPS-compliant plugin server binaries
mkdir -p server/dist-fips
@echo "Setting up FIPS build environment..."

# Docker authentication is handled by CI (setup-chainctl)
@if ! docker manifest inspect $(FIPS_IMAGE) >/dev/null 2>&1; then \
echo "Docker authentication failed. Ensure setup-chainctl configured Docker authentication."; \
echo "Trying fallback authentication if credentials are available..."; \
if [ -n "$(CHAINGUARD_DEV_USERNAME)" ] && [ -n "$(CHAINGUARD_DEV_TOKEN)" ]; then \
echo "Using username/token authentication..."; \
echo "$(CHAINGUARD_DEV_TOKEN)" | docker login cgr.dev --username "$(CHAINGUARD_DEV_USERNAME)" --password-stdin; \
else \
echo "Warning: No authentication available. FIPS build may fail."; \
fi; \
else \
echo "βœ… Docker authentication is working"; \
fi

# Create local cache directory for CI/ACT compatibility
mkdir -p $(PWD)/.build-cache

# Try FIPS build with error handling
@if docker run --rm \
--entrypoint="" \
-v $(PWD):/plugin \
-v $(PWD)/.build-cache:/root/.cache \
-w /plugin/server \
$(FIPS_IMAGE) \
sh -c "CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags fips -ldflags '$(LDFLAGS)' -trimpath -buildvcs=false -o dist-fips/plugin-linux-amd64-fips"; then \
echo "FIPS plugin server build completed: server/dist-fips/plugin-linux-amd64-fips"; \
else \
echo "FIPS build failed - likely authentication issue with $(FIPS_IMAGE)"; \
echo "Creating placeholder to indicate FIPS build was attempted but failed"; \
echo "FIPS_BUILD_FAILED" > server/dist-fips/FIPS_BUILD_FAILED.txt; \
exit 1; \
fi
endif

## Builds the server, if it exists, for Linux architectures only.
.PHONY: server-linux
server-linux: templates-archive
Expand Down Expand Up @@ -150,33 +207,62 @@ endif
## Generates a tar bundle of the plugin for install.
.PHONY: bundle
bundle:
rm -rf dist/
mkdir -p dist/$(PLUGIN_NAME)
cp $(MANIFEST_FILE) dist/$(PLUGIN_NAME)/
cp -r webapp/pack dist/$(PLUGIN_NAME)/
ifneq ($(wildcard LICENSE.txt),)
cp -r LICENSE.txt dist/$(PLUGIN_NAME)/
endif
ifneq ($(wildcard NOTICE.txt),)
cp -r NOTICE.txt dist/$(PLUGIN_NAME)/
endif
ifneq ($(wildcard $(ASSETS_DIR)/.),)
cp -r $(ASSETS_DIR) dist/$(PLUGIN_NAME)/
rm -rf dist/$(PLUGIN_ID)
mkdir -p dist/$(PLUGIN_ID)
cp $(MANIFEST_FILE) dist/$(PLUGIN_ID)/
cp -r webapp/pack dist/$(PLUGIN_ID)/
$(call copy_bundle_files,dist)
ifneq ($(HAS_SERVER),)
mkdir -p dist/$(PLUGIN_ID)/server
cp -r server/dist dist/$(PLUGIN_ID)/server/
endif
ifneq ($(HAS_PUBLIC),)
cp -r public dist/$(PLUGIN_NAME)/public/
ifneq ($(HAS_WEBAPP),)
mkdir -p dist/$(PLUGIN_ID)/webapp
cp -r webapp/dist dist/$(PLUGIN_ID)/webapp/
endif
cd dist && tar -cvzf $(BUNDLE_NAME) $(PLUGIN_ID)

@echo "==> Normal plugin built at: dist/$(BUNDLE_NAME)"

## Generates a tar bundle of the FIPS plugin for install.
.PHONY: bundle-fips
bundle-fips:
rm -rf dist-fips/
mkdir -p dist-fips/$(PLUGIN_ID)
./build/bin/manifest dist-fips
$(call copy_bundle_files,dist-fips)
ifneq ($(HAS_SERVER),)
mkdir -p dist/$(PLUGIN_NAME)/server
cp -r server/dist dist/$(PLUGIN_NAME)/server/
mkdir -p dist-fips/$(PLUGIN_ID)/server/dist
# Copy FIPS binaries but rename them to standard names for server compatibility
if [ -f server/dist-fips/plugin-linux-amd64-fips ]; then \
cp server/dist-fips/plugin-linux-amd64-fips dist-fips/$(PLUGIN_ID)/server/dist/plugin-linux-amd64; \
fi
# Copy any other FIPS binaries and rename them
for file in server/dist-fips/plugin-*-fips*; do \
if [ -f "$$file" ]; then \
target=$$(basename "$$file" | sed 's/-fips//g'); \
cp "$$file" "dist-fips/$(PLUGIN_ID)/server/dist/$$target"; \
fi; \
done
endif
ifneq ($(HAS_WEBAPP),)
mkdir -p dist/$(PLUGIN_NAME)/webapp
cp -r webapp/dist dist/$(PLUGIN_NAME)/webapp/
if [ -d webapp/dist ]; then \
mkdir -p dist-fips/$(PLUGIN_ID)/webapp && \
cp -r webapp/dist dist-fips/$(PLUGIN_ID)/webapp/; \
else \
echo "Error: webapp/dist not found, but HAS_WEBAPP is set. Run 'make webapp' first."; \
exit 1; \
fi
endif
# Use webpack pack for webapp bundle
cp -r webapp/pack dist-fips/$(PLUGIN_ID)/
ifeq ($(shell uname),Darwin)
cd dist-fips && tar --disable-copyfile -cvzf $(PLUGIN_ID)-$(PLUGIN_VERSION)-fips.tar.gz $(PLUGIN_ID)
else
cd dist-fips && tar -cvzf $(PLUGIN_ID)-$(PLUGIN_VERSION)-fips.tar.gz $(PLUGIN_ID)
endif
cd dist && tar -cvzf $(BUNDLE_NAME) $(PLUGIN_NAME)

@echo plugin built at: dist/$(BUNDLE_NAME)
@echo "==> FIPS plugin built at: dist-fips/$(PLUGIN_ID)-$(PLUGIN_VERSION)-fips.tar.gz"

info: ## Display build information
@echo "Build Number: $(BUILD_NUMBER)"
Expand All @@ -190,6 +276,25 @@ info: ## Display build information
.PHONY: dist
dist: apply server webapp bundle

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

## Builds both normal and FIPS distributions.
.PHONY: dist-all
dist-all: clean
@echo "==> Building both normal and FIPS distributions in parallel..."
$(MAKE) dist
@if $(MAKE) dist-fips; then \
echo "==> Both distributions built successfully:"; \
echo " Normal: dist/$$(./build/bin/manifest id)-$$(./build/bin/manifest version).tar.gz"; \
echo " FIPS: dist-fips/$$(./build/bin/manifest id)-$$(./build/bin/manifest version)-fips.tar.gz"; \
else \
echo "==> FIPS build failed, continuing with normal distribution only:"; \
echo " Normal: dist/$$(./build/bin/manifest id)-$$(./build/bin/manifest version).tar.gz"; \
echo " FIPS: Build failed - check Docker/credentials"; \
fi

## Builds and bundles the plugin for Linux only.
.PHONY: dist-linux
dist-linux: apply server-linux webapp bundle
Expand Down Expand Up @@ -315,11 +420,13 @@ kill: detach
.PHONY: clean
clean:
rm -rf bin
rm -rf dist
rm -rf dist/
rm -rf dist-fips/
rm -rf webapp/pack
ifneq ($(HAS_SERVER),)
rm -fr server/coverage.txt
rm -fr server/dist
rm -fr server/dist-fips
endif
ifneq ($(HAS_WEBAPP),)
rm -fr webapp/junit.xml
Expand Down Expand Up @@ -355,17 +462,17 @@ live-watch-webapp: apply
.PHONY: deploy-to-mattermost-directory
deploy-to-mattermost-directory:
./build/bin/pluginctl disable $(PLUGIN_ID)
mkdir -p $(FOCALBOARD_PLUGIN_PATH)
cp $(MANIFEST_FILE) $(FOCALBOARD_PLUGIN_PATH)/
cp -r webapp/pack $(FOCALBOARD_PLUGIN_PATH)/
cp -r $(ASSETS_DIR) $(FOCALBOARD_PLUGIN_PATH)/
cp -r public $(FOCALBOARD_PLUGIN_PATH)/
mkdir -p $(FOCALBOARD_PLUGIN_PATH)/server
cp -r server/dist $(FOCALBOARD_PLUGIN_PATH)/server/
mkdir -p $(FOCALBOARD_PLUGIN_PATH)/webapp
cp -r webapp/dist $(FOCALBOARD_PLUGIN_PATH)/webapp/
mkdir -p $(BOARD_PLUGIN_PATH)
cp $(MANIFEST_FILE) $(BOARD_PLUGIN_PATH)/
cp -r webapp/pack $(BOARD_PLUGIN_PATH)/
cp -r $(ASSETS_DIR) $(BOARD_PLUGIN_PATH)/
cp -r public $(BOARD_PLUGIN_PATH)/
mkdir -p $(BOARD_PLUGIN_PATH)/server
cp -r server/dist $(BOARD_PLUGIN_PATH)/server/
mkdir -p $(BOARD_PLUGIN_PATH)/webapp
cp -r webapp/dist $(BOARD_PLUGIN_PATH)/webapp/
./build/bin/pluginctl enable $(PLUGIN_ID)
@echo plugin built at: $(FOCALBOARD_PLUGIN_PATH)
@echo plugin built at: $(BOARD_PLUGIN_PATH)

# Help documentation Γ  la https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help:
Expand Down
Loading
Loading