snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 00:29:55 +05:00
commit 240db4e2a7
15309 changed files with 2173406 additions and 0 deletions

View File

@@ -0,0 +1,578 @@
#!/usr/bin/env bash
set -Eeuo pipefail
log() {
printf '[cloud-agent-install] %s\n' "$*" >&2
}
is_true() {
case "${1:-}" in
1 | true | TRUE | yes | YES) return 0 ;;
*) return 1 ;;
esac
}
is_git_work_tree() {
[ "$(git -C "${1:-}" rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]
}
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
cd "$ROOT"
NVM_VERSION="${CLOUD_AGENT_NVM_VERSION:-0.40.3}"
export GOPATH="${GOPATH:-$HOME/go}"
export PATH="/usr/local/go/bin:$GOPATH/bin:/usr/local/bin:$PATH"
required_go_version() {
local version_file="$ROOT/server/.go-version"
if [ ! -f "$version_file" ]; then
log "server/.go-version is missing; cannot determine the required Go version."
return 1
fi
tr -d '[:space:]' < "$version_file"
}
current_go_version() {
command -v go >/dev/null 2>&1 || return 1
go version | awk '{print $3}' | sed 's/^go//'
}
install_go() {
local version="$1"
local go_arch
case "$(dpkg --print-architecture)" in
amd64) go_arch=amd64 ;;
arm64) go_arch=arm64 ;;
*)
log "Unsupported Go architecture: $(dpkg --print-architecture)"
return 1
;;
esac
local tarball="/tmp/go${version}.linux-${go_arch}.tar.gz"
log "Downloading Go ${version} (${go_arch})."
curl --retry 3 --retry-delay 5 -fsSL "https://go.dev/dl/go${version}.linux-${go_arch}.tar.gz" -o "$tarball"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "$tarball"
sudo ln -sfnT /usr/local/go/bin/go /usr/local/bin/go
sudo ln -sfnT /usr/local/go/bin/gofmt /usr/local/bin/gofmt
rm -f "$tarball"
}
persist_go_path() {
local marker="# mattermost-cloud-agent-go-path"
local rc="${HOME}/.bashrc"
if [ -f "$rc" ] && grep -Fq "$marker" "$rc"; then
return 0
fi
{
echo "$marker"
echo 'export GOPATH="${GOPATH:-$HOME/go}"'
echo 'export PATH="/usr/local/go/bin:$GOPATH/bin:$PATH"'
} >> "$rc"
}
ensure_go() {
export GOPATH="${GOPATH:-$HOME/go}"
export PATH="/usr/local/go/bin:/usr/local/bin:${GOPATH}/bin:${PATH}"
local required current
required="$(required_go_version)"
current="$(current_go_version || true)"
if [ "$current" != "$required" ]; then
log "Go ${current:-not found} does not match server/.go-version (${required}); installing."
install_go "$required"
hash -r
persist_go_path
current="$(current_go_version || true)"
fi
if [ "$current" != "$required" ]; then
log "Go is ${current:-not found} after install; expected ${required}."
return 1
fi
log "Using $(go version)"
}
required_node_version() {
if [ -n "${CLOUD_AGENT_NODE_VERSION:-}" ]; then
printf '%s\n' "${CLOUD_AGENT_NODE_VERSION#v}"
return 0
fi
local version_file="$ROOT/.nvmrc"
if [ ! -f "$version_file" ]; then
log ".nvmrc is missing; cannot determine the required Node version."
return 1
fi
tr -d '[:space:]' < "$version_file" | sed 's/^v//'
}
current_node_version() {
command -v node >/dev/null 2>&1 || return 1
node --version | sed 's/^v//'
}
# .nvmrc may pin a major or major.minor (e.g. 24.11); node --version is always
# major.minor.patch. Require an exact match on every component the pin specifies.
node_version_matches() {
local required="$1"
local current="$2"
if [ -z "$required" ] || [ -z "$current" ]; then
return 1
fi
local r1 r2 r3 c1 c2 c3
IFS=. read -r r1 r2 r3 <<< "$required"
IFS=. read -r c1 c2 c3 <<< "$current"
[ "$c1" = "$r1" ] || return 1
[ -z "${r2:-}" ] || [ "$c2" = "$r2" ] || return 1
[ -z "${r3:-}" ] || [ "$c3" = "$r3" ] || return 1
return 0
}
ensure_nvm() {
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
if [ -s "$NVM_DIR/nvm.sh" ]; then
# shellcheck source=/dev/null
. "$NVM_DIR/nvm.sh"
return 0
fi
log "nvm is not installed; cloning v${NVM_VERSION}."
git clone --depth 1 --branch "v${NVM_VERSION}" https://github.com/nvm-sh/nvm.git "$NVM_DIR"
# shellcheck source=/dev/null
. "$NVM_DIR/nvm.sh"
}
link_node_bins() {
local resolved="$1"
local bindir="${NVM_DIR}/versions/node/v${resolved}/bin"
if [ ! -x "${bindir}/node" ]; then
log "nvm Node binary not found at ${bindir}/node."
return 1
fi
sudo ln -sfn "${bindir}/node" /usr/local/bin/node
sudo ln -sfn "${bindir}/npm" /usr/local/bin/npm
sudo ln -sfn "${bindir}/npx" /usr/local/bin/npx
}
persist_node_path() {
local marker="# mattermost-cloud-agent-node-path"
local rc="${HOME}/.bashrc"
if [ -f "$rc" ] && grep -Fq "$marker" "$rc"; then
return 0
fi
{
echo "$marker"
printf 'export NVM_DIR=%q\n' "${NVM_DIR:-$HOME/.nvm}"
echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"'
} >> "$rc"
}
install_node() {
local version="$1"
ensure_nvm
log "Installing Node ${version} via nvm."
nvm install "$version"
nvm alias default "$version"
nvm use "$version"
local resolved
resolved="$(current_node_version)"
link_node_bins "$resolved"
}
ensure_node() {
local required current
required="$(required_node_version)"
ensure_nvm
nvm use "$required" >/dev/null 2>&1 || true
current="$(current_node_version || true)"
if ! node_version_matches "$required" "$current"; then
log "Node ${current:-not found} does not match .nvmrc (${required}); installing."
install_node "$required"
hash -r
persist_node_path
current="$(current_node_version || true)"
fi
if ! node_version_matches "$required" "$current"; then
log "Node is ${current:-not found} after install; expected ${required}."
return 1
fi
link_node_bins "$current"
persist_node_path
if ! command -v npm >/dev/null 2>&1; then
log "npm is not available after Node ${current} install."
return 1
fi
log "Using node $(node --version) and npm $(npm --version)"
}
enterprise_build_dir() {
case "$BUILD_ENTERPRISE_DIR" in
/*) realpath -m "$BUILD_ENTERPRISE_DIR" ;;
*) realpath -m "$ROOT/server/$BUILD_ENTERPRISE_DIR" ;;
esac
}
default_enterprise_checkout() {
realpath -m "$ROOT/../enterprise"
}
find_enterprise_checkout() {
local candidates=()
if [ -n "${ENTERPRISE_CHECKOUT_DIR:-}" ]; then
candidates+=("$ENTERPRISE_CHECKOUT_DIR")
fi
if [ -n "${ENTERPRISE_DIR:-}" ]; then
candidates+=("$ENTERPRISE_DIR")
fi
if [ -n "${BUILD_ENTERPRISE_DIR:-}" ]; then
case "$BUILD_ENTERPRISE_DIR" in
/*) candidates+=("$BUILD_ENTERPRISE_DIR") ;;
*) candidates+=("$ROOT/server/$BUILD_ENTERPRISE_DIR") ;;
esac
fi
candidates+=(
"$(default_enterprise_checkout)"
"$ROOT/../../enterprise"
"$HOME/enterprise"
)
local candidate
for candidate in "${candidates[@]}"; do
if is_git_work_tree "$candidate"; then
realpath -m "$candidate"
return 0
fi
done
return 1
}
enterprise_clone_url() {
printf 'https://github.com/mattermost/enterprise.git\n'
}
requested_enterprise_branch() {
local branch
if [ -n "${ENTERPRISE_BRANCH:-}" ]; then
branch="$ENTERPRISE_BRANCH"
elif ! branch="$(git -C "$ROOT" symbolic-ref --quiet --short HEAD 2>/dev/null)"; then
return 1
fi
if ! git check-ref-format --branch "$branch" >/dev/null 2>&1; then
return 1
fi
printf '%s\n' "$branch"
}
enterprise_branch_exists() {
local branch="$1"
local url
url="$(enterprise_clone_url)"
GIT_TERMINAL_PROMPT=0 git ls-remote --exit-code --heads "$url" "refs/heads/$branch" >/dev/null 2>&1 && return 0
local status=$?
if [ "$status" -eq 2 ]; then
return 1
fi
if ! command -v gh >/dev/null 2>&1; then
return 2
fi
local exists
if ! exists="$(
gh api graphql \
-f query="query(\$qualifiedName: String!) { repository(owner: \"mattermost\", name: \"enterprise\") { ref(qualifiedName: \$qualifiedName) { id } } }" \
-f qualifiedName="refs/heads/$branch" \
--jq '.data.repository.ref != null' 2>/dev/null
)"; then
return 2
fi
[ "$exists" = "true" ]
}
matching_enterprise_branch() {
local branch
if ! branch="$(requested_enterprise_branch)"; then
log "No valid Enterprise branch was requested; using Enterprise's default branch."
return 1
fi
local status
if enterprise_branch_exists "$branch"; then
printf '%s\n' "$branch"
return 0
else
status=$?
fi
if [ "$status" -eq 1 ]; then
log "Enterprise branch $branch does not exist; using Enterprise's default branch."
return 1
fi
log "Could not verify Enterprise branch $branch; attempting it before the default branch."
printf '%s\n' "$branch"
}
can_clone_into() {
local dest="$1"
local parent
parent="$(dirname "$dest")"
if [ ! -d "$parent" ] || [ ! -w "$parent" ] || [ ! -x "$parent" ]; then
return 1
fi
if [ -L "$dest" ]; then
return 1
fi
if [ ! -e "$dest" ]; then
return 0
fi
if is_git_work_tree "$dest"; then
return 0
fi
if [ ! -d "$dest" ] || [ ! -w "$dest" ] || [ ! -x "$dest" ]; then
return 1
fi
local entries
if ! entries="$(ls -A "$dest" 2>/dev/null)"; then
return 1
fi
[ -z "$entries" ]
}
publish_enterprise_checkout() {
local source="$1"
local dest="$2"
if mv -T -n "$source" "$dest" && [ ! -e "$source" ]; then
return 0
fi
rm -rf "$source"
if is_git_work_tree "$dest"; then
log "Another process populated Enterprise checkout at $dest; reusing it."
return 0
fi
log "Could not publish Enterprise checkout at $dest."
return 1
}
clone_enterprise_ref() {
local dest="$1"
local url="$2"
shift 2
local clone_args=("$@")
local temp
if ! temp="$(mktemp -d "$(dirname "$dest")/.enterprise-clone.XXXXXX")"; then
return 1
fi
if GIT_TERMINAL_PROMPT=0 git clone "${clone_args[@]}" "$url" "$temp"; then
publish_enterprise_checkout "$temp" "$dest"
return $?
fi
rm -rf "$temp"
if ! command -v gh >/dev/null 2>&1; then
return 1
fi
log "git clone failed; retrying with GitHub CLI."
if ! temp="$(mktemp -d "$(dirname "$dest")/.enterprise-clone.XXXXXX")"; then
return 1
fi
if gh repo clone mattermost/enterprise "$temp" -- "${clone_args[@]}"; then
publish_enterprise_checkout "$temp" "$dest"
return $?
fi
rm -rf "$temp"
return 1
}
enterprise_clone_dest() {
local sibling
sibling="$(default_enterprise_checkout)"
if can_clone_into "$sibling"; then
printf '%s\n' "$sibling"
return 0
fi
realpath -m "$HOME/enterprise"
}
clone_enterprise_checkout() {
local dest="$1"
local url
url="$(enterprise_clone_url)"
if [ -z "$dest" ] || [ "$dest" = "/" ] || [ "$(basename "$dest")" != "enterprise" ]; then
log "Refusing unsafe enterprise clone dest: ${dest:-<empty>}"
return 1
fi
if ! can_clone_into "$dest"; then
log "Refusing unusable enterprise clone dest: $dest"
return 1
fi
if [ -e "$dest" ]; then
if is_git_work_tree "$dest"; then
return 0
fi
rmdir "$dest"
fi
log "Enterprise checkout missing; cloning mattermost/enterprise into $dest."
log "Git-triggered automations stay single-repo; repositoryDependencies only scopes the GitHub token."
mkdir -p "$(dirname "$dest")"
local clone_args=(--depth 1 --single-branch)
local branch
if branch="$(matching_enterprise_branch)"; then
clone_args+=(--branch "$branch")
log "Trying matching Enterprise branch $branch."
fi
if clone_enterprise_ref "$dest" "$url" "${clone_args[@]}"; then
return 0
fi
if [ -n "${branch:-}" ]; then
log "Could not clone matching Enterprise branch $branch; retrying with the default branch."
clone_args=(--depth 1 --single-branch)
clone_enterprise_ref "$dest" "$url" "${clone_args[@]}" && return 0
fi
log "Failed to clone mattermost/enterprise. repositoryDependencies must include github.com/mattermost/enterprise so the GitHub token can access it."
return 1
}
persist_build_enterprise_dir() {
local target="$1"
export BUILD_ENTERPRISE_DIR="$target"
local default_target
default_target="$(default_enterprise_checkout)"
if [ "$target" = "$default_target" ]; then
return 0
fi
local override="$ROOT/server/config.override.mk"
if [ -f "$override" ] && grep -q '^BUILD_ENTERPRISE_DIR' "$override"; then
return 0
fi
printf 'BUILD_ENTERPRISE_DIR := %s\n' "$target" >> "$override"
log "Wrote BUILD_ENTERPRISE_DIR to $override so make uses the cloned checkout."
}
ensure_enterprise_checkout() {
if is_true "${CLOUD_AGENT_SKIP_ENTERPRISE:-false}"; then
log "Skipping enterprise verification because CLOUD_AGENT_SKIP_ENTERPRISE is set."
return 0
fi
local target
if target="$(find_enterprise_checkout)"; then
persist_build_enterprise_dir "$target"
log "Enterprise checkout ready at $target."
return 0
fi
local dest
dest="$(enterprise_clone_dest)"
clone_enterprise_checkout "$dest"
target="$(realpath -m "$dest")"
if ! is_git_work_tree "$target"; then
log "Enterprise clone completed but checkout was not found at $dest."
return 1
fi
persist_build_enterprise_dir "$target"
log "Enterprise checkout ready at $target."
}
hydrate_go_dependencies() {
if is_true "${CLOUD_AGENT_SKIP_GO_DEPS:-false}"; then
log "Skipping Go dependency hydration."
return 0
fi
if [ -d server ]; then
if [ -n "${BUILD_ENTERPRISE_DIR:-}" ]; then
local enterprise_dir
enterprise_dir="$(enterprise_build_dir)"
log "Hydrating Go workspace with BUILD_ENTERPRISE_DIR=$enterprise_dir"
(
cd server
BUILD_ENTERPRISE_DIR="$enterprise_dir" make setup-go-work
go mod download
if [ -f public/go.mod ]; then
(cd public && go mod download)
fi
)
else
log "Hydrating Go workspace with server/Makefile default enterprise path."
(
cd server
make setup-go-work
go mod download
if [ -f public/go.mod ]; then
(cd public && go mod download)
fi
)
fi
fi
}
hydrate_webapp_dependencies() {
if is_true "${CLOUD_AGENT_SKIP_WEBAPP_DEPS:-false}"; then
log "Skipping webapp dependency hydration."
return 0
fi
if [ -f webapp/package.json ]; then
log "Hydrating webapp dependencies."
(cd webapp && make node_modules)
fi
}
hydrate_playwright_dependencies() {
if is_true "${CLOUD_AGENT_SKIP_PLAYWRIGHT_DEPS:-false}"; then
log "Skipping Playwright dependency hydration."
return 0
fi
if [ -f e2e-tests/playwright/package-lock.json ]; then
log "Hydrating Playwright dependencies."
(cd e2e-tests/playwright && npm ci)
fi
}
ensure_go
ensure_node
ensure_enterprise_checkout
hydrate_go_dependencies
hydrate_webapp_dependencies
hydrate_playwright_dependencies
log "AWS CLI: $(aws --version 2>&1 || printf 'not available')"
log "Install hook complete."