mirror of
https://github.com/element-hq/synapse.git
synced 2026-10-23 23:53:58 +00:00
Merge branch 'develop' into madlittlemods/move-start-background-updates2
Conflicts: changelog.d/19036.misc synapse/app/homeserver.py tests/rest/admin/test_room.py tests/util/test_task_scheduler.py
This commit is contained in:
939 files changed
+63005
-30776
No files matched your search
@@ -7,4 +7,4 @@ if command -v yum &> /dev/null; then
|
||||
fi
|
||||
|
||||
# Install a Rust toolchain
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.82.0 -y --profile minimal
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y --profile minimal
|
||||
@@ -29,7 +29,7 @@ which is under the Unlicense licence.
|
||||
{{- with .TestCases -}}
|
||||
{{- /* Passing tests are first */ -}}
|
||||
{{- range . -}}
|
||||
{{- if eq .Result "PASS" -}}
|
||||
{{- if and (eq .Result "PASS") (not $settings.HideSuccessfulTests) -}}
|
||||
::group::{{ "\033" }}[0;32m✅{{ " " }}{{- .Name -}}
|
||||
{{- "\033" -}}[0;37m ({{if $settings.ShowTestStatus}}{{.Result}}; {{end}}{{ .Duration -}}
|
||||
{{- with .Coverage -}}
|
||||
@@ -49,7 +49,8 @@ which is under the Unlicense licence.
|
||||
|
||||
{{- /* Then skipped tests are second */ -}}
|
||||
{{- range . -}}
|
||||
{{- if eq .Result "SKIP" -}}
|
||||
{{- /* Skipped tests are also purposefully hidden if "HideSuccessfulTests" is enabled */ -}}
|
||||
{{- if and (eq .Result "SKIP") (not $settings.HideSuccessfulTests) -}}
|
||||
::group::{{ "\033" }}[0;33m🚧{{ " " }}{{- .Name -}}
|
||||
{{- "\033" -}}[0;37m ({{if $settings.ShowTestStatus}}{{.Result}}; {{end}}{{ .Duration -}}
|
||||
{{- with .Coverage -}}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
#
|
||||
# Copyright (C) 2023 New Vector, Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# See the GNU Affero General Public License for more details:
|
||||
# <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
#
|
||||
# Originally licensed under the Apache License, Version 2.0:
|
||||
# <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
#
|
||||
# [This file includes modifications made by New Vector Limited]
|
||||
#
|
||||
#
|
||||
|
||||
# Wraps `auditwheel repair` to first check if we're repairing a potentially abi3
|
||||
# compatible wheel, if so rename the wheel before repairing it.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
from zipfile import ZipFile
|
||||
|
||||
from packaging.tags import Tag
|
||||
from packaging.utils import parse_wheel_filename
|
||||
from packaging.version import Version
|
||||
|
||||
|
||||
def check_is_abi3_compatible(wheel_file: str) -> None:
|
||||
"""Check the contents of the built wheel for any `.so` files that are *not*
|
||||
abi3 compatible.
|
||||
"""
|
||||
|
||||
with ZipFile(wheel_file, "r") as wheel:
|
||||
for file in wheel.namelist():
|
||||
if not file.endswith(".so"):
|
||||
continue
|
||||
|
||||
if not file.endswith(".abi3.so"):
|
||||
raise Exception(f"Found non-abi3 lib: {file}")
|
||||
|
||||
|
||||
def cpython(wheel_file: str, name: str, version: Version, tag: Tag) -> str:
|
||||
"""Replaces the cpython wheel file with a ABI3 compatible wheel"""
|
||||
|
||||
if tag.abi == "abi3":
|
||||
# Nothing to do.
|
||||
return wheel_file
|
||||
|
||||
check_is_abi3_compatible(wheel_file)
|
||||
|
||||
# HACK: it seems that some older versions of pip will consider a wheel marked
|
||||
# as macosx_11_0 as incompatible with Big Sur. I haven't done the full archaeology
|
||||
# here; there are some clues in
|
||||
# https://github.com/pantsbuild/pants/pull/12857
|
||||
# https://github.com/pypa/pip/issues/9138
|
||||
# https://github.com/pypa/packaging/pull/319
|
||||
# Empirically this seems to work, note that macOS 11 and 10.16 are the same,
|
||||
# both versions are valid for backwards compatibility.
|
||||
platform = tag.platform.replace("macosx_11_0", "macosx_10_16")
|
||||
abi3_tag = Tag(tag.interpreter, "abi3", platform)
|
||||
|
||||
dirname = os.path.dirname(wheel_file)
|
||||
new_wheel_file = os.path.join(
|
||||
dirname,
|
||||
f"{name}-{version}-{abi3_tag}.whl",
|
||||
)
|
||||
|
||||
os.rename(wheel_file, new_wheel_file)
|
||||
|
||||
print("Renamed wheel to", new_wheel_file)
|
||||
|
||||
return new_wheel_file
|
||||
|
||||
|
||||
def main(wheel_file: str, dest_dir: str, archs: Optional[str]) -> None:
|
||||
"""Entry point"""
|
||||
|
||||
# Parse the wheel file name into its parts. Note that `parse_wheel_filename`
|
||||
# normalizes the package name (i.e. it converts matrix_synapse ->
|
||||
# matrix-synapse), which is not what we want.
|
||||
_, version, build, tags = parse_wheel_filename(os.path.basename(wheel_file))
|
||||
name = os.path.basename(wheel_file).split("-")[0]
|
||||
|
||||
if len(tags) != 1:
|
||||
# We expect only a wheel file with only a single tag
|
||||
raise Exception(f"Unexpectedly found multiple tags: {tags}")
|
||||
|
||||
tag = next(iter(tags))
|
||||
|
||||
if build:
|
||||
# We don't use build tags in Synapse
|
||||
raise Exception(f"Unexpected build tag: {build}")
|
||||
|
||||
# If the wheel is for cpython then convert it into an abi3 wheel.
|
||||
if tag.interpreter.startswith("cp"):
|
||||
wheel_file = cpython(wheel_file, name, version, tag)
|
||||
|
||||
# Finally, repair the wheel.
|
||||
if archs is not None:
|
||||
# If we are given archs then we are on macos and need to use
|
||||
# `delocate-listdeps`.
|
||||
subprocess.run(["delocate-listdeps", wheel_file], check=True)
|
||||
subprocess.run(
|
||||
["delocate-wheel", "--require-archs", archs, "-w", dest_dir, wheel_file],
|
||||
check=True,
|
||||
)
|
||||
else:
|
||||
subprocess.run(["auditwheel", "repair", "-w", dest_dir, wheel_file], check=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Tag wheel as abi3 and repair it.")
|
||||
|
||||
parser.add_argument(
|
||||
"--wheel-dir",
|
||||
"-w",
|
||||
metavar="WHEEL_DIR",
|
||||
help="Directory to store delocated wheels",
|
||||
required=True,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--require-archs",
|
||||
metavar="archs",
|
||||
default=None,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"wheel_file",
|
||||
metavar="WHEEL_FILE",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
wheel_file = args.wheel_file
|
||||
wheel_dir = args.wheel_dir
|
||||
archs = args.require_archs
|
||||
|
||||
main(wheel_file, wheel_dir, archs)
|
||||
@@ -35,49 +35,58 @@ IS_PR = os.environ["GITHUB_REF"].startswith("refs/pull/")
|
||||
|
||||
# First calculate the various trial jobs.
|
||||
#
|
||||
# For PRs, we only run each type of test with the oldest Python version supported (which
|
||||
# is Python 3.9 right now)
|
||||
# For PRs, we only run each type of test with the oldest and newest Python
|
||||
# version that's supported. The oldest version ensures we don't accidentally
|
||||
# introduce syntax or code that's too new, and the newest ensures we don't use
|
||||
# code that's been dropped in the latest supported Python version.
|
||||
|
||||
trial_sqlite_tests = [
|
||||
{
|
||||
"python-version": "3.9",
|
||||
"python-version": "3.10",
|
||||
"database": "sqlite",
|
||||
"extras": "all",
|
||||
}
|
||||
},
|
||||
{
|
||||
"python-version": "3.14",
|
||||
"database": "sqlite",
|
||||
"extras": "all",
|
||||
},
|
||||
]
|
||||
|
||||
if not IS_PR:
|
||||
# Otherwise, check all supported Python versions.
|
||||
#
|
||||
# Avoiding running all of these versions on every PR saves on CI time.
|
||||
trial_sqlite_tests.extend(
|
||||
{
|
||||
"python-version": version,
|
||||
"database": "sqlite",
|
||||
"extras": "all",
|
||||
}
|
||||
for version in ("3.10", "3.11", "3.12", "3.13")
|
||||
for version in ("3.11", "3.12", "3.13")
|
||||
)
|
||||
|
||||
# Only test postgres against the earliest and latest Python versions that we
|
||||
# support in order to save on CI time.
|
||||
trial_postgres_tests = [
|
||||
{
|
||||
"python-version": "3.9",
|
||||
"python-version": "3.10",
|
||||
"database": "postgres",
|
||||
"postgres-version": "13",
|
||||
"postgres-version": "14",
|
||||
"extras": "all",
|
||||
}
|
||||
},
|
||||
{
|
||||
"python-version": "3.14",
|
||||
"database": "postgres",
|
||||
"postgres-version": "17",
|
||||
"extras": "all",
|
||||
},
|
||||
]
|
||||
|
||||
if not IS_PR:
|
||||
trial_postgres_tests.append(
|
||||
{
|
||||
"python-version": "3.13",
|
||||
"database": "postgres",
|
||||
"postgres-version": "17",
|
||||
"extras": "all",
|
||||
}
|
||||
)
|
||||
|
||||
# Ensure that Synapse passes unit tests even with no extra dependencies installed.
|
||||
trial_no_extra_tests = [
|
||||
{
|
||||
"python-version": "3.9",
|
||||
"python-version": "3.10",
|
||||
"database": "sqlite",
|
||||
"extras": "",
|
||||
}
|
||||
@@ -99,24 +108,24 @@ set_output("trial_test_matrix", test_matrix)
|
||||
|
||||
# First calculate the various sytest jobs.
|
||||
#
|
||||
# For each type of test we only run on bullseye on PRs
|
||||
# For each type of test we only run on bookworm on PRs
|
||||
|
||||
|
||||
sytest_tests = [
|
||||
{
|
||||
"sytest-tag": "bullseye",
|
||||
"sytest-tag": "bookworm",
|
||||
},
|
||||
{
|
||||
"sytest-tag": "bullseye",
|
||||
"sytest-tag": "bookworm",
|
||||
"postgres": "postgres",
|
||||
},
|
||||
{
|
||||
"sytest-tag": "bullseye",
|
||||
"sytest-tag": "bookworm",
|
||||
"postgres": "multi-postgres",
|
||||
"workers": "workers",
|
||||
},
|
||||
{
|
||||
"sytest-tag": "bullseye",
|
||||
"sytest-tag": "bookworm",
|
||||
"postgres": "multi-postgres",
|
||||
"workers": "workers",
|
||||
"reactor": "asyncio",
|
||||
@@ -127,11 +136,11 @@ if not IS_PR:
|
||||
sytest_tests.extend(
|
||||
[
|
||||
{
|
||||
"sytest-tag": "bullseye",
|
||||
"sytest-tag": "bookworm",
|
||||
"reactor": "asyncio",
|
||||
},
|
||||
{
|
||||
"sytest-tag": "bullseye",
|
||||
"sytest-tag": "bookworm",
|
||||
"postgres": "postgres",
|
||||
"reactor": "asyncio",
|
||||
},
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# wraps `gotestfmt`, hiding output from successful packages unless
|
||||
# all tests passed.
|
||||
|
||||
set -o pipefail
|
||||
set -e
|
||||
|
||||
# tee the test results to a log, whilst also piping them into gotestfmt,
|
||||
# telling it to hide successful results, so that we can clearly see
|
||||
# unsuccessful results.
|
||||
tee complement.log | gotestfmt -hide successful-packages
|
||||
|
||||
# gotestfmt will exit non-zero if there were any failures, so if we got to this
|
||||
# point, we must have had a successful result.
|
||||
echo "All tests successful; showing all test results"
|
||||
|
||||
# Pipe the test results back through gotestfmt, showing all results.
|
||||
# The log file consists of JSON lines giving the test results, interspersed
|
||||
# with regular stdout lines (including reports of downloaded packages).
|
||||
grep '^{"Time":' complement.log | gotestfmt
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# this script is run by GitHub Actions in a plain `jammy` container; it
|
||||
# - installs the minimal system requirements, and poetry;
|
||||
# - patches the project definition file to refer to old versions only;
|
||||
# - creates a venv with these old versions using poetry; and finally
|
||||
# - invokes `trial` to run the tests with old deps.
|
||||
|
||||
set -ex
|
||||
|
||||
# Prevent virtualenv from auto-updating pip to an incompatible version
|
||||
export VIRTUALENV_NO_DOWNLOAD=1
|
||||
|
||||
# TODO: in the future, we could use an implementation of
|
||||
# https://github.com/python-poetry/poetry/issues/3527
|
||||
# https://github.com/pypa/pip/issues/8085
|
||||
# to select the lowest possible versions, rather than resorting to this sed script.
|
||||
|
||||
# Patch the project definitions in-place:
|
||||
# - Replace all lower and tilde bounds with exact bounds
|
||||
# - Replace all caret bounds---but not the one that defines the supported Python version!
|
||||
# - Delete all lines referring to psycopg2 --- so no testing of postgres support.
|
||||
# - Use pyopenssl 17.0, which is the oldest version that works with
|
||||
# a `cryptography` compiled against OpenSSL 1.1.
|
||||
# - Omit systemd: we're not logging to journal here.
|
||||
|
||||
sed -i \
|
||||
-e "s/[~>]=/==/g" \
|
||||
-e '/^python = "^/!s/\^/==/g' \
|
||||
-e "/psycopg2/d" \
|
||||
-e 's/pyOpenSSL = "==16.0.0"/pyOpenSSL = "==17.0.0"/' \
|
||||
-e '/systemd/d' \
|
||||
pyproject.toml
|
||||
|
||||
echo "::group::Patched pyproject.toml"
|
||||
cat pyproject.toml
|
||||
echo "::endgroup::"
|
||||
@@ -10,7 +10,6 @@ alias block='{ set +x; } 2>/dev/null; func() { echo "::group::$*"; set -x; }; fu
|
||||
alias endblock='{ set +x; } 2>/dev/null; func() { echo "::endgroup::"; set -x; }; func'
|
||||
|
||||
block Install Complement Dependencies
|
||||
sudo apt-get -qq update && sudo apt-get install -qqy libolm3 libolm-dev
|
||||
go install -v github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
|
||||
endblock
|
||||
|
||||
|
||||
@@ -26,3 +26,8 @@ c4268e3da64f1abb5b31deaeb5769adb6510c0a7
|
||||
# Update black to 23.1.0 (https://github.com/matrix-org/synapse/pull/15103)
|
||||
9bb2eac71962970d02842bca441f4bcdbbf93a11
|
||||
|
||||
# Use type hinting generics in standard collections (https://github.com/element-hq/synapse/pull/19046)
|
||||
fc244bb592aa481faf28214a2e2ce3bb4e95d990
|
||||
|
||||
# Write union types as X | Y where possible (https://github.com/element-hq/synapse/pull/19111)
|
||||
fcac7e0282b074d4bd3414d1c9c181e9701875d9
|
||||
@@ -1,23 +1,93 @@
|
||||
version: 2
|
||||
# As dependabot is currently only run on a weekly basis, we raise the
|
||||
# open-pull-requests-limit to 10 (from the default of 5) to better ensure we
|
||||
# don't continuously grow a backlog of updates.
|
||||
updates:
|
||||
- # "pip" is the correct setting for poetry, per https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
|
||||
package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: "increase-if-necessary"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# Group patch updates to packages together into a single PR, as they rarely
|
||||
# if ever contain breaking changes that need to be reviewed separately.
|
||||
#
|
||||
# Less PRs means a streamlined review process.
|
||||
#
|
||||
# Python packages follow semantic versioning, and tend to only introduce
|
||||
# breaking changes in major version bumps. Thus, we'll group minor and patch
|
||||
# versions together.
|
||||
groups:
|
||||
minor-and-patches:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "*"
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
# Prevent pulling packages that were recently updated to help mitigate
|
||||
# supply chain attacks. 14 days was taken from the recommendation at
|
||||
# https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns
|
||||
# where the author noted that 9/10 attacks would have been mitigated by a
|
||||
# two week cooldown.
|
||||
#
|
||||
# The cooldown only applies to general updates; security updates will still
|
||||
# be pulled in as soon as possible.
|
||||
cooldown:
|
||||
default-days: 14
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/docker"
|
||||
open-pull-requests-limit: 10
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# For container versions, breaking changes are also typically only introduced in major
|
||||
# package bumps.
|
||||
groups:
|
||||
minor-and-patches:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "*"
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
cooldown:
|
||||
default-days: 14
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 10
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# Similarly for GitHub Actions, breaking changes are typically only introduced in major
|
||||
# package bumps.
|
||||
groups:
|
||||
minor-and-patches:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "*"
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
cooldown:
|
||||
default-days: 14
|
||||
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: "lockfile-only"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# The Rust ecosystem is special in that breaking changes are often introduced
|
||||
# in minor version bumps, as packages typically stay pre-1.0 for a long time.
|
||||
# Thus we specifically keep minor version bumps separate in their own PRs.
|
||||
groups:
|
||||
patches:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "*"
|
||||
update-types:
|
||||
- "patch"
|
||||
cooldown:
|
||||
default-days: 14
|
||||
@@ -0,0 +1,208 @@
|
||||
# Re-usable workflow (https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows)
|
||||
name: Reusable Complement testing
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
use_latest_deps:
|
||||
type: boolean
|
||||
default: false
|
||||
use_twisted_trunk:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Control the permissions granted to `GITHUB_TOKEN`.
|
||||
permissions:
|
||||
# `actions/checkout` reads the repository (also see
|
||||
# https://github.com/actions/checkout/tree/de0fac2e4500dabe0009e67214ff5f5447ce83dd/#recommended-permissions)
|
||||
contents: read
|
||||
|
||||
env:
|
||||
RUST_VERSION: 1.87.0
|
||||
|
||||
jobs:
|
||||
complement:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arrangement: monolith
|
||||
database: SQLite
|
||||
|
||||
- arrangement: monolith
|
||||
database: Postgres
|
||||
|
||||
- arrangement: workers
|
||||
database: Postgres
|
||||
|
||||
steps:
|
||||
- name: Checkout synapse codebase
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
path: synapse
|
||||
|
||||
# Log Docker system info for debugging (compare with your local environment) and
|
||||
# tracking GitHub runner changes over time (can easily compare a run from last
|
||||
# week with the current one in question).
|
||||
- run: docker system info
|
||||
shell: bash
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
# We use `poetry` in `complement.sh`
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
poetry-version: "2.4.1"
|
||||
# Matches the `path` where we checkout Synapse above
|
||||
working-directory: "synapse"
|
||||
|
||||
- name: Prepare Complement's Prerequisites
|
||||
run: synapse/.ci/scripts/setup_complement_prerequisites.sh
|
||||
|
||||
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
||||
with:
|
||||
cache-dependency-path: complement/go.sum
|
||||
go-version-file: complement/go.mod
|
||||
|
||||
# This step is specific to the 'Twisted trunk' test run:
|
||||
- name: Patch dependencies
|
||||
if: ${{ inputs.use_twisted_trunk }}
|
||||
run: |
|
||||
set -x
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt-get install -yqq python3 pipx
|
||||
pipx install poetry==2.4.1
|
||||
|
||||
poetry remove -n twisted
|
||||
poetry add -n --extras tls git+https://github.com/twisted/twisted.git#trunk
|
||||
poetry lock
|
||||
working-directory: synapse
|
||||
|
||||
# Run the image sanity check test first as this is the first thing we want to know
|
||||
# about (are we actually testing what we expect?) and we don't want to debug
|
||||
# downstream failures (wild goose chase).
|
||||
- name: Sanity check Complement image
|
||||
id: run_sanity_check_complement_image_test
|
||||
# -p=1: We're using `-p 1` to force the test packages to run serially as GHA boxes
|
||||
# are underpowered and don't like running tons of Synapse instances at once.
|
||||
# -json: Output JSON format so that gotestfmt can parse it.
|
||||
#
|
||||
# tee /tmp/gotest-sanity-check-complement.log: We tee the raw JSON to a
|
||||
# file so we can re-process it later for better formatting with gotestfmt
|
||||
# (and upload it as an artifact).
|
||||
#
|
||||
# We deliberately do not dump the raw JSON to the terminal as it is huge
|
||||
# and unreadable. Instead we pipe it through `jq` to print a compact,
|
||||
# real-time progress view: for each `go test -json` event we print only
|
||||
# completed tests (`pass`/`skip`/`fail`, including subtests), dropping the
|
||||
# noisy `run`/`output` events and package-level lines. The full detail
|
||||
# lives in the raw log we tee to the file above. Non-JSON lines (e.g. the
|
||||
# image build output and `set -x` traces that `go test -json` does not
|
||||
# wrap) are passed through unchanged rather than parsed, so we still see
|
||||
# them and the filter never aborts the pipeline.
|
||||
run: |
|
||||
set -o pipefail
|
||||
COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh --in-repo -p 1 -json -run 'TestSynapseVersion/Synapse_version_matches_current_git_checkout' 2>&1 \
|
||||
| tee /tmp/gotest-sanity-check-complement.log \
|
||||
| jq -rR --unbuffered '. as $raw | (try fromjson catch $raw) | if type == "object" then (select(.Action=="pass" or .Action=="fail" or .Action=="skip") | select(.Test) | "\(.Action|ascii_upcase) \(.Test) \(.Elapsed)s") else $raw end'
|
||||
shell: bash
|
||||
env:
|
||||
POSTGRES: ${{ (matrix.database == 'Postgres') && 1 || '' }}
|
||||
WORKERS: ${{ (matrix.arrangement == 'workers') && 1 || '' }}
|
||||
|
||||
- name: Formatted sanity check Complement test logs
|
||||
# Always run this step if we attempted to run the Complement tests.
|
||||
if: always() && steps.run_sanity_check_complement_image_test.outcome != 'skipped'
|
||||
# We do not hide successful tests in `gotestfmt` here as the list of sanity
|
||||
# check tests is so short. Feel free to change this when we get more tests.
|
||||
#
|
||||
# Note that the `-hide` argument is interpreted by `gotestfmt`. From it,
|
||||
# it derives several values under `$settings` and passes them to our
|
||||
# custom `.ci/complement_package.gotpl` template to render the output.
|
||||
run: cat /tmp/gotest-sanity-check-complement.log | gotestfmt -hide "successful-downloads,empty-packages"
|
||||
|
||||
- name: Run Complement Tests
|
||||
id: run_complement_tests
|
||||
# -p=1: We're using `-p 1` to force the test packages to run serially as GHA boxes
|
||||
# are underpowered and don't like running tons of Synapse instances at once.
|
||||
# -json: Output JSON format so that gotestfmt can parse it.
|
||||
#
|
||||
# tee /tmp/gotest-complement.log: We tee the raw JSON to a file so we can
|
||||
# re-process it later for better formatting with gotestfmt (and upload it
|
||||
# as an artifact), and pipe it through `jq` for a compact, real-time
|
||||
# progress view. See the sanity check step above for details on the jq
|
||||
# filter.
|
||||
run: |
|
||||
set -o pipefail
|
||||
COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh -p 1 -json 2>&1 \
|
||||
| tee /tmp/gotest-complement.log \
|
||||
| jq -rR --unbuffered '. as $raw | (try fromjson catch $raw) | if type == "object" then (select(.Action=="pass" or .Action=="fail" or .Action=="skip") | select(.Test) | "\(.Action|ascii_upcase) \(.Test) \(.Elapsed)s") else $raw end'
|
||||
shell: bash
|
||||
env:
|
||||
POSTGRES: ${{ (matrix.database == 'Postgres') && 1 || '' }}
|
||||
WORKERS: ${{ (matrix.arrangement == 'workers') && 1 || '' }}
|
||||
TEST_ONLY_IGNORE_POETRY_LOCKFILE: ${{ inputs.use_latest_deps && 1 || '' }}
|
||||
TEST_ONLY_SKIP_DEP_HASH_VERIFICATION: ${{ inputs.use_twisted_trunk && 1 || '' }}
|
||||
|
||||
- name: Formatted Complement test logs (only failing are shown)
|
||||
# Always run this step if we attempted to run the Complement tests.
|
||||
if: always() && steps.run_complement_tests.outcome != 'skipped'
|
||||
# Hide successful tests in order to reduce the verbosity of the otherwise very large output.
|
||||
#
|
||||
# Note that the `-hide` argument is interpreted by `gotestfmt`. From it,
|
||||
# it derives several values under `$settings` and passes them to our
|
||||
# custom `.ci/complement_package.gotpl` template to render the output.
|
||||
run: cat /tmp/gotest-complement.log | gotestfmt -hide "successful-downloads,successful-tests,empty-packages"
|
||||
|
||||
- name: Run in-repo Complement Tests
|
||||
id: run_in_repo_complement_tests
|
||||
# -p=1: We're using `-p 1` to force the test packages to run serially as GHA boxes
|
||||
# are underpowered and don't like running tons of Synapse instances at once.
|
||||
# -json: Output JSON format so that gotestfmt can parse it.
|
||||
#
|
||||
# tee /tmp/gotest-in-repo-complement.log: We tee the raw JSON to a file so
|
||||
# we can re-process it later for better formatting with gotestfmt (and
|
||||
# upload it as an artifact), and pipe it through `jq` for a compact,
|
||||
# real-time progress view. See the sanity check step above for details on
|
||||
# the jq filter.
|
||||
run: |
|
||||
set -o pipefail
|
||||
COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh --in-repo -p 1 -json 2>&1 \
|
||||
| tee /tmp/gotest-in-repo-complement.log \
|
||||
| jq -rR --unbuffered '. as $raw | (try fromjson catch $raw) | if type == "object" then (select(.Action=="pass" or .Action=="fail" or .Action=="skip") | select(.Test) | "\(.Action|ascii_upcase) \(.Test) \(.Elapsed)s") else $raw end'
|
||||
shell: bash
|
||||
env:
|
||||
POSTGRES: ${{ (matrix.database == 'Postgres') && 1 || '' }}
|
||||
WORKERS: ${{ (matrix.arrangement == 'workers') && 1 || '' }}
|
||||
TEST_ONLY_IGNORE_POETRY_LOCKFILE: ${{ inputs.use_latest_deps && 1 || '' }}
|
||||
TEST_ONLY_SKIP_DEP_HASH_VERIFICATION: ${{ inputs.use_twisted_trunk && 1 || '' }}
|
||||
|
||||
- name: Formatted in-repo Complement test logs (only failing are shown)
|
||||
# Always run this step if we attempted to run the Complement tests.
|
||||
if: always() && steps.run_in_repo_complement_tests.outcome != 'skipped'
|
||||
# Hide successful tests in order to reduce the verbosity of the otherwise very large output.
|
||||
#
|
||||
# Note that the `-hide` argument is interpreted by `gotestfmt`. From it,
|
||||
# it derives several values under `$settings` and passes them to our
|
||||
# custom `.ci/complement_package.gotpl` template to render the output.
|
||||
run: cat /tmp/gotest-in-repo-complement.log | gotestfmt -hide "successful-downloads,successful-tests,empty-packages"
|
||||
|
||||
- name: Upload Complement logs
|
||||
# Always upload the logs (as artifacts) if we attempted to run the
|
||||
# Complement tests, so we can debug failures without scrolling through
|
||||
# the (very large) raw output in the build log.
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
# The matrix values keep the name unique across the three matrix
|
||||
# combinations (upload-artifact rejects duplicate names within a run).
|
||||
name: Complement Logs - ${{ job.status }} - (${{ matrix.arrangement }}, ${{ matrix.database }})
|
||||
path: |
|
||||
/tmp/gotest-sanity-check-complement.log
|
||||
/tmp/gotest-complement.log
|
||||
/tmp/gotest-in-repo-complement.log
|
||||
@@ -28,10 +28,10 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Extract version from pyproject.toml
|
||||
# Note: explicitly requesting bash will mean bash is invoked with `-eo pipefail`, see
|
||||
@@ -41,21 +41,53 @@ jobs:
|
||||
echo "SYNAPSE_VERSION=$(grep "^version" pyproject.toml | sed -E 's/version\s*=\s*["]([^"]*)["]/\1/')" >> $GITHUB_ENV
|
||||
|
||||
- name: Log in to DockerHub
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@780049a30b6ff5c378a9e7b389d15ece7a204888 # v4.1.3
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
audience: ${{ secrets.TS_AUDIENCE }}
|
||||
tags: tag:github-actions
|
||||
|
||||
- name: Compute vault jwt role name
|
||||
id: vault-jwt-role
|
||||
run: |
|
||||
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Get team registry token
|
||||
id: import-secrets
|
||||
uses: hashicorp/vault-action@892a26828f195e65540a40b4768ae4571f51ebfc # v4.0.0
|
||||
with:
|
||||
url: https://vault.infra.ci.i.element.dev
|
||||
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
||||
path: service-management/github-actions
|
||||
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
||||
method: jwt
|
||||
secrets: |
|
||||
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
||||
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
||||
|
||||
- name: Login to Element OCI Registry
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
registry: oci-push.vpn.infra.element.io
|
||||
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
||||
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
||||
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
with:
|
||||
push: true
|
||||
labels: |
|
||||
@@ -64,6 +96,7 @@ jobs:
|
||||
tags: |
|
||||
docker.io/matrixdotorg/synapse
|
||||
ghcr.io/element-hq/synapse
|
||||
oci-push.vpn.infra.element.io/synapse
|
||||
file: "docker/Dockerfile"
|
||||
platforms: ${{ matrix.platform }}
|
||||
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
||||
@@ -75,7 +108,7 @@ jobs:
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: digests-${{ matrix.suffix }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
@@ -90,40 +123,73 @@ jobs:
|
||||
repository:
|
||||
- docker.io/matrixdotorg/synapse
|
||||
- ghcr.io/element-hq/synapse
|
||||
- oci-push.vpn.infra.element.io/synapse
|
||||
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Log in to DockerHub
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
if: ${{ startsWith(matrix.repository, 'docker.io') }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
if: ${{ startsWith(matrix.repository, 'ghcr.io') }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@780049a30b6ff5c378a9e7b389d15ece7a204888 # v4.1.3
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
audience: ${{ secrets.TS_AUDIENCE }}
|
||||
tags: tag:github-actions
|
||||
|
||||
- name: Compute vault jwt role name
|
||||
id: vault-jwt-role
|
||||
run: |
|
||||
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Get team registry token
|
||||
id: import-secrets
|
||||
uses: hashicorp/vault-action@892a26828f195e65540a40b4768ae4571f51ebfc # v4.0.0
|
||||
with:
|
||||
url: https://vault.infra.ci.i.element.dev
|
||||
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
||||
path: service-management/github-actions
|
||||
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
||||
method: jwt
|
||||
secrets: |
|
||||
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
||||
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
||||
|
||||
- name: Login to Element OCI Registry
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
registry: oci-push.vpn.infra.element.io
|
||||
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
||||
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
|
||||
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
||||
|
||||
- name: Calculate docker image tag
|
||||
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
|
||||
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
|
||||
with:
|
||||
images: ${{ matrix.repository }}
|
||||
flavor: |
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Deploy documentation PR preview
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [ "Prepare documentation PR preview" ]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
netlify:
|
||||
if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# There's a 'download artifact' action, but it hasn't been updated for the workflow_run action
|
||||
# (https://github.com/actions/download-artifact/issues/60) so instead we get this mess:
|
||||
- name: 📥 Download artifact
|
||||
uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
|
||||
with:
|
||||
workflow: docs-pr.yaml
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: book
|
||||
path: book
|
||||
|
||||
- name: 📤 Deploy to Netlify
|
||||
uses: matrix-org/netlify-pr-preview@9805cd123fc9a7e421e35340a05e1ebc5dee46b5 # v3
|
||||
with:
|
||||
path: book
|
||||
owner: ${{ github.event.workflow_run.head_repository.owner.login }}
|
||||
branch: ${{ github.event.workflow_run.head_branch }}
|
||||
revision: ${{ github.event.workflow_run.head_sha }}
|
||||
token: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
site_id: ${{ secrets.NETLIFY_SITE_ID }}
|
||||
desc: Documentation preview
|
||||
deployment_env: PR Documentation Preview
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
name: GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
# Fetch all history so that the schema_versions script works.
|
||||
fetch-depth: 0
|
||||
@@ -21,10 +21,10 @@ jobs:
|
||||
- name: Setup mdbook
|
||||
uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08 # v2.0.0
|
||||
with:
|
||||
mdbook-version: '0.4.17'
|
||||
mdbook-version: '0.5.2'
|
||||
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
cp book/welcome_and_overview.html book/index.html
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: book
|
||||
path: book
|
||||
@@ -50,12 +50,12 @@ jobs:
|
||||
name: Check links in documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Setup mdbook
|
||||
uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08 # v2.0.0
|
||||
with:
|
||||
mdbook-version: '0.4.17'
|
||||
mdbook-version: '0.5.2'
|
||||
|
||||
- name: Setup htmltest
|
||||
run: |
|
||||
@@ -64,8 +64,17 @@ jobs:
|
||||
tar zxf htmltest_0.17.0_linux_amd64.tar.gz
|
||||
|
||||
- name: Test links with htmltest
|
||||
# Build the book with `./` as the site URL (to make checks on 404.html possible)
|
||||
# Then run htmltest (without checking external links since that involves the network and is slow).
|
||||
run: |
|
||||
# Build the book with `./` as the site URL (to make checks on 404.html possible)
|
||||
MDBOOK_OUTPUT__HTML__SITE_URL="./" mdbook build
|
||||
./htmltest book --skip-external
|
||||
|
||||
# Delete the contents of the print.html file, as it can raise false
|
||||
# positives during link checking.
|
||||
#
|
||||
# We empty out the file, instead of deleting it, as doing so would
|
||||
# just cause htmltest to complain that links to it were invalid.
|
||||
# Ideally `htmltest` would have an option to ignore specific files
|
||||
# instead.
|
||||
echo '<!DOCTYPE HTML>' > book/print.html
|
||||
|
||||
./htmltest book --conf docs/.htmltest.yml
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
needs:
|
||||
- pre
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
# Fetch all history so that the schema_versions script works.
|
||||
fetch-depth: 0
|
||||
@@ -58,13 +58,13 @@ jobs:
|
||||
- name: Setup mdbook
|
||||
uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08 # v2.0.0
|
||||
with:
|
||||
mdbook-version: '0.4.17'
|
||||
mdbook-version: '0.5.2'
|
||||
|
||||
- name: Set version of docs
|
||||
run: echo 'window.SYNAPSE_VERSION = "${{ needs.pre.outputs.branch-version }}";' > ./docs/website_files/version.js
|
||||
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
|
||||
# Deploy to the target directory.
|
||||
- name: Deploy to gh pages
|
||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
||||
uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./book
|
||||
|
||||
@@ -9,7 +9,9 @@ on:
|
||||
env:
|
||||
# We use nightly so that `fmt` correctly groups together imports, and
|
||||
# clippy correctly fixes up the benchmarks.
|
||||
RUST_VERSION: nightly-2025-06-24
|
||||
#
|
||||
# Note: This should match the nightly rust version in `tests.yml`.
|
||||
RUST_VERSION: nightly-2025-03-27
|
||||
|
||||
jobs:
|
||||
fixup:
|
||||
@@ -18,20 +20,20 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
components: clippy, rustfmt
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Setup Poetry
|
||||
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
install-project: "false"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
|
||||
- name: Run ruff check
|
||||
continue-on-error: true
|
||||
@@ -47,6 +49,6 @@ jobs:
|
||||
- run: cargo fmt
|
||||
continue-on-error: true
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@778341af668090896ca464160c2def5d1d1a3eb0 # v6.0.1
|
||||
- uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0
|
||||
with:
|
||||
commit_message: "Attempt to fix linting"
|
||||
@@ -42,19 +42,19 @@ jobs:
|
||||
if: needs.check_repo.outputs.should_run_workflow == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
# The dev dependencies aren't exposed in the wheel metadata (at least with current
|
||||
# poetry-core versions), so we install with poetry.
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
extras: "all"
|
||||
# Dump installed versions for debugging.
|
||||
- run: poetry run pip list > before.txt
|
||||
@@ -77,13 +77,13 @@ jobs:
|
||||
postgres-version: "14"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: sudo apt-get -qq install xmlsec1
|
||||
- name: Set up PostgreSQL ${{ matrix.postgres-version }}
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
-e POSTGRES_PASSWORD=postgres \
|
||||
-e POSTGRES_INITDB_ARGS="--lc-collate C --lc-ctype C --encoding UTF8" \
|
||||
postgres:${{ matrix.postgres-version }}
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: pip install .[all,test]
|
||||
@@ -126,7 +126,6 @@ jobs:
|
||||
-exec echo "::endgroup::" \;
|
||||
|| true
|
||||
|
||||
|
||||
sytest:
|
||||
needs: check_repo
|
||||
if: needs.check_repo.outputs.should_run_workflow == 'true'
|
||||
@@ -139,9 +138,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- sytest-tag: bullseye
|
||||
- sytest-tag: bookworm
|
||||
|
||||
- sytest-tag: bullseye
|
||||
- sytest-tag: bookworm
|
||||
postgres: postgres
|
||||
workers: workers
|
||||
redis: redis
|
||||
@@ -152,13 +151,13 @@ jobs:
|
||||
BLACKLIST: ${{ matrix.workers && 'synapse-blacklist-with-workers' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Ensure sytest runs `pip install`
|
||||
# Delete the lockfile so sytest will `pip install` rather than `poetry install`
|
||||
@@ -173,7 +172,7 @@ jobs:
|
||||
if: ${{ always() }}
|
||||
run: /sytest/scripts/tap_to_gha.pl /logs/results.tap
|
||||
- name: Upload SyTest logs
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: Sytest Logs - ${{ job.status }} - (${{ join(matrix.*, ', ') }})
|
||||
@@ -181,44 +180,12 @@ jobs:
|
||||
/logs/results.tap
|
||||
/logs/**/*.log*
|
||||
|
||||
|
||||
complement:
|
||||
uses: ./.github/workflows/complement_tests.yml
|
||||
needs: check_repo
|
||||
if: "!failure() && !cancelled() && needs.check_repo.outputs.should_run_workflow == 'true'"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arrangement: monolith
|
||||
database: SQLite
|
||||
|
||||
- arrangement: monolith
|
||||
database: Postgres
|
||||
|
||||
- arrangement: workers
|
||||
database: Postgres
|
||||
|
||||
steps:
|
||||
- name: Check out synapse codebase
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: synapse
|
||||
|
||||
- name: Prepare Complement's Prerequisites
|
||||
run: synapse/.ci/scripts/setup_complement_prerequisites.sh
|
||||
|
||||
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
cache-dependency-path: complement/go.sum
|
||||
go-version-file: complement/go.mod
|
||||
|
||||
- run: |
|
||||
set -o pipefail
|
||||
TEST_ONLY_IGNORE_POETRY_LOCKFILE=1 POSTGRES=${{ (matrix.database == 'Postgres') && 1 || '' }} WORKERS=${{ (matrix.arrangement == 'workers') && 1 || '' }} COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh -json 2>&1 | synapse/.ci/scripts/gotestfmt
|
||||
shell: bash
|
||||
name: Run Complement Tests
|
||||
with:
|
||||
use_latest_deps: true
|
||||
|
||||
# Open an issue if the build fails, so we know about it.
|
||||
# Only do this if we're not experimenting with this action in a PR.
|
||||
@@ -234,7 +201,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -16,8 +16,8 @@ jobs:
|
||||
name: "Check locked dependencies have sdists"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: pip install tomli
|
||||
|
||||
@@ -33,29 +33,33 @@ jobs:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout specific branch (debug build)
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
- name: Checkout clean copy of develop (scheduled build)
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
if: github.event_name == 'schedule'
|
||||
with:
|
||||
ref: develop
|
||||
- name: Checkout clean copy of master (on-push)
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
if: github.event_name == 'push'
|
||||
with:
|
||||
ref: master
|
||||
# We use `poetry` in `complement.sh`
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
poetry-version: "2.4.1"
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Work out labels for complement image
|
||||
id: meta
|
||||
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
|
||||
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}/complement-synapse
|
||||
tags: |
|
||||
@@ -69,6 +73,7 @@ jobs:
|
||||
run: |
|
||||
for TAG in ${{ join(fromJson(steps.meta.outputs.json).tags, ' ') }}; do
|
||||
echo "tag and push $TAG"
|
||||
docker tag complement-synapse $TAG
|
||||
# `localhost/complement-synapse` should match the image created by `scripts-dev/complement.sh`
|
||||
docker tag localhost/complement-synapse $TAG
|
||||
docker push $TAG
|
||||
done
|
||||
@@ -5,7 +5,7 @@ name: Build release artifacts
|
||||
on:
|
||||
# we build on PRs and develop to (hopefully) get early warning
|
||||
# of things breaking (but only build one set of debs). PRs skip
|
||||
# building wheels on macOS & ARM.
|
||||
# building wheels on ARM.
|
||||
pull_request:
|
||||
push:
|
||||
branches: ["develop", "release-*"]
|
||||
@@ -27,8 +27,8 @@ jobs:
|
||||
name: "Calculate list of debian distros"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- id: set-distros
|
||||
@@ -50,23 +50,27 @@ jobs:
|
||||
name: "Build .deb packages"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
# Prevent all Debian package builds from being cancelled
|
||||
# when one of them fails. Especially helpful when things are
|
||||
# flaky during a release.
|
||||
#
|
||||
# `fail-fast` defaults to true and applies to the entire test matrix
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro: ${{ fromJson(needs.get-distros.outputs.distros) }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
path: src
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
with:
|
||||
install: true
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Set up docker layer caching
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
@@ -74,7 +78,7 @@ jobs:
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
@@ -101,7 +105,7 @@ jobs:
|
||||
echo "ARTIFACT_NAME=${DISTRO#*:}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload debs as artifacts
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: debs-${{ steps.artifact-name.outputs.ARTIFACT_NAME }}
|
||||
path: debs/*
|
||||
@@ -114,47 +118,45 @@ jobs:
|
||||
os:
|
||||
- ubuntu-24.04
|
||||
- ubuntu-24.04-arm
|
||||
- macos-14 # This uses arm64
|
||||
- macos-15-intel # This uses x86-64
|
||||
# is_pr is a flag used to exclude certain jobs from the matrix on PRs.
|
||||
# It is not read by the rest of the workflow.
|
||||
is_pr:
|
||||
- ${{ startsWith(github.ref, 'refs/pull/') }}
|
||||
|
||||
exclude:
|
||||
# Don't build macos wheels on PR CI.
|
||||
- is_pr: true
|
||||
os: "macos-15-intel"
|
||||
- is_pr: true
|
||||
os: "macos-14"
|
||||
# Don't build aarch64 wheels on PR CI.
|
||||
- is_pr: true
|
||||
os: "ubuntu-24.04-arm"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
# setup-python@v4 doesn't impose a default python version. Need to use 3.x
|
||||
# here, because `python` on osx points to Python 2.7.
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: python -m pip install cibuildwheel==3.0.0
|
||||
run: python -m pip install cibuildwheel==3.2.1
|
||||
|
||||
- name: Only build a single wheel on PR
|
||||
if: startsWith(github.ref, 'refs/pull/')
|
||||
run: echo "CIBW_BUILD="cp39-manylinux_*"" >> $GITHUB_ENV
|
||||
run: echo "CIBW_BUILD="cp310-manylinux_*"" >> $GITHUB_ENV
|
||||
|
||||
- name: Build wheels
|
||||
run: python -m cibuildwheel --output-dir wheelhouse
|
||||
env:
|
||||
# Skip testing for platforms which various libraries don't have wheels
|
||||
# for, and so need extra build deps.
|
||||
CIBW_TEST_SKIP: pp3*-* *i686* *musl*
|
||||
# The platforms that we build for are determined by the
|
||||
# `tool.cibuildwheel.skip` option in `pyproject.toml`.
|
||||
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
# We skip testing wheels for the following platforms in CI:
|
||||
#
|
||||
# pp3*-* (PyPy wheels) broke in CI (TODO: investigate).
|
||||
# musl: (TODO: investigate).
|
||||
CIBW_TEST_SKIP: pp3*-* *musl*
|
||||
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Wheel-${{ matrix.os }}
|
||||
path: ./wheelhouse/*.whl
|
||||
@@ -165,8 +167,8 @@ jobs:
|
||||
if: ${{ !startsWith(github.ref, 'refs/pull/') }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
@@ -175,7 +177,7 @@ jobs:
|
||||
- name: Build sdist
|
||||
run: python -m build --sdist
|
||||
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Sdist
|
||||
path: dist/*.tar.gz
|
||||
@@ -191,7 +193,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download all workflow run artifacts
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
- name: Build a tarball for the debs
|
||||
# We need to merge all the debs uploads into one folder, then compress
|
||||
# that.
|
||||
@@ -200,16 +202,11 @@ jobs:
|
||||
mv debs*/* debs/
|
||||
tar -cvJf debs.tar.xz debs
|
||||
- name: Attach to release
|
||||
# Pinned to work around https://github.com/softprops/action-gh-release/issues/445
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v0.1.15
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
files: |
|
||||
Sdist/*
|
||||
Wheel*/*
|
||||
debs.tar.xz
|
||||
# if it's not already published, keep the release as a draft.
|
||||
draft: true
|
||||
# mark it as a prerelease if the tag contains 'rc'.
|
||||
prerelease: ${{ contains(github.ref, 'rc') }}
|
||||
run: |
|
||||
gh release upload "${{ github.ref_name }}" \
|
||||
Sdist/* \
|
||||
Wheel*/* \
|
||||
debs.tar.xz \
|
||||
--repo ${{ github.repository }}
|
||||
@@ -14,8 +14,8 @@ jobs:
|
||||
name: Ensure Synapse config schema is valid
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Install check-jsonschema
|
||||
@@ -40,8 +40,8 @@ jobs:
|
||||
name: Ensure generated documentation is up-to-date
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Install PyYAML
|
||||
|
||||
+167
-190
@@ -13,6 +13,16 @@ concurrency:
|
||||
|
||||
env:
|
||||
RUST_VERSION: 1.87.0
|
||||
# This nightly is roughly the last to be branded 1.87.0.
|
||||
#
|
||||
# We know this, as 1.87.0 was branched from master on 2025-03-28. Shortly
|
||||
# afterwards, nightlies were then branded as 1.88.0. See
|
||||
# https://releases.rs/docs/1.87.0/ for where we get the dates.
|
||||
#
|
||||
# Technically the last 1.87.0 nightly was 2025-03-29, but that all depends on
|
||||
# at which time of day they cut the release and when the nightly is built.
|
||||
# It's safer for future releases to just do the day before.
|
||||
RUST_NIGHTLY_VERSION: nightly-2025-03-27 # last nightly before 1.88.0
|
||||
|
||||
jobs:
|
||||
# Job to detect what has changed so we don't run e.g. Rust checks on PRs that
|
||||
@@ -25,60 +35,70 @@ jobs:
|
||||
integration: ${{ !startsWith(github.ref, 'refs/pull/') || steps.filter.outputs.integration }}
|
||||
linting: ${{ !startsWith(github.ref, 'refs/pull/') || steps.filter.outputs.linting }}
|
||||
linting_readme: ${{ !startsWith(github.ref, 'refs/pull/') || steps.filter.outputs.linting_readme }}
|
||||
golangci: ${{ !startsWith(github.ref, 'refs/pull/') || steps.filter.outputs.golangci }}
|
||||
steps:
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: filter
|
||||
# We only check on PRs
|
||||
if: startsWith(github.ref, 'refs/pull/')
|
||||
with:
|
||||
filters: |
|
||||
rust:
|
||||
- 'rust/**'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- '.rustfmt.toml'
|
||||
- '.github/workflows/tests.yml'
|
||||
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
|
||||
id: filter
|
||||
# We only check on PRs
|
||||
if: startsWith(github.ref, 'refs/pull/')
|
||||
with:
|
||||
filters: |
|
||||
rust:
|
||||
- 'rust/**'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- '.rustfmt.toml'
|
||||
- '.github/workflows/tests.yml'
|
||||
|
||||
trial:
|
||||
- 'synapse/**'
|
||||
- 'tests/**'
|
||||
- 'rust/**'
|
||||
- '.ci/scripts/calculate_jobs.py'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- 'pyproject.toml'
|
||||
- 'poetry.lock'
|
||||
- '.github/workflows/tests.yml'
|
||||
trial:
|
||||
- 'synapse/**'
|
||||
- 'tests/**'
|
||||
- 'rust/**'
|
||||
- '.ci/scripts/calculate_jobs.py'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- 'pyproject.toml'
|
||||
- 'poetry.lock'
|
||||
- '.github/workflows/tests.yml'
|
||||
|
||||
integration:
|
||||
- 'synapse/**'
|
||||
- 'rust/**'
|
||||
- 'docker/**'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- 'pyproject.toml'
|
||||
- 'poetry.lock'
|
||||
- 'docker/**'
|
||||
- '.ci/**'
|
||||
- 'scripts-dev/complement.sh'
|
||||
- '.github/workflows/tests.yml'
|
||||
integration:
|
||||
- 'synapse/**'
|
||||
- 'rust/**'
|
||||
- 'docker/**'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- 'pyproject.toml'
|
||||
- 'poetry.lock'
|
||||
- 'docker/**'
|
||||
- '.ci/**'
|
||||
- '.github/workflows/tests.yml'
|
||||
- 'scripts-dev/complement.sh'
|
||||
- '.github/workflows/complement_tests.yml'
|
||||
- 'complement/**'
|
||||
|
||||
linting:
|
||||
- 'synapse/**'
|
||||
- 'docker/**'
|
||||
- 'tests/**'
|
||||
- 'scripts-dev/**'
|
||||
- 'contrib/**'
|
||||
- 'synmark/**'
|
||||
- 'stubs/**'
|
||||
- '.ci/**'
|
||||
- 'mypy.ini'
|
||||
- 'pyproject.toml'
|
||||
- 'poetry.lock'
|
||||
- '.github/workflows/tests.yml'
|
||||
linting:
|
||||
- 'synapse/**'
|
||||
- 'docker/**'
|
||||
- 'tests/**'
|
||||
- 'scripts-dev/**'
|
||||
- 'contrib/**'
|
||||
- 'synmark/**'
|
||||
- 'stubs/**'
|
||||
- '.ci/**'
|
||||
- 'mypy.ini'
|
||||
- 'pyproject.toml'
|
||||
- 'poetry.lock'
|
||||
- '.github/workflows/tests.yml'
|
||||
|
||||
linting_readme:
|
||||
- 'README.rst'
|
||||
golangci:
|
||||
- 'complement/**/*.go'
|
||||
- 'complement/.golangci.yml'
|
||||
- 'complement/go.mod'
|
||||
- 'complement/go.sum'
|
||||
- '.github/workflows/tests.yml'
|
||||
|
||||
linting_readme:
|
||||
- 'README.rst'
|
||||
|
||||
check-sampleconfig:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -86,16 +106,16 @@ jobs:
|
||||
if: ${{ needs.changes.outputs.linting == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
extras: "all"
|
||||
- run: poetry run scripts-dev/generate_sample_config.sh --check
|
||||
- run: poetry run scripts-dev/config-lint.sh
|
||||
@@ -106,18 +126,18 @@ jobs:
|
||||
if: ${{ needs.changes.outputs.linting == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: "pip install 'click==8.1.1' 'GitPython>=3.1.20'"
|
||||
- run: "pip install 'click==8.1.1' 'GitPython>=3.1.20' 'sqlglot>=28.0.0'"
|
||||
- run: scripts-dev/check_schema_delta.py --force-colors
|
||||
|
||||
check-lockfile:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: .ci/scripts/check_lockfile.py
|
||||
@@ -129,12 +149,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Setup Poetry
|
||||
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
install-project: "false"
|
||||
|
||||
- name: Run ruff check
|
||||
@@ -151,13 +171,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Setup Poetry
|
||||
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
@@ -169,12 +189,12 @@ jobs:
|
||||
# https://github.com/matrix-org/synapse/pull/15376#issuecomment-1498983775
|
||||
# To make CI green, err towards caution and install the project.
|
||||
install-project: "true"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
|
||||
# Cribbed from
|
||||
# https://github.com/AustinScola/mypy-cache-github-action/blob/85ea4f2972abed39b33bd02c36e341b28ca59213/src/restore.ts#L10-L17
|
||||
- name: Restore/persist mypy's cache
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: |
|
||||
.mypy_cache
|
||||
@@ -187,19 +207,20 @@ jobs:
|
||||
lint-crlf:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Check line endings
|
||||
run: scripts-dev/check_line_terminators.sh
|
||||
|
||||
lint-newsfile:
|
||||
if: ${{ (github.base_ref == 'develop' || contains(github.base_ref, 'release-')) && github.actor != 'dependabot[bot]' }}
|
||||
# Only run on pull_request events, targeting develop/release branches, and skip when the PR author is dependabot[bot].
|
||||
if: ${{ github.event_name == 'pull_request' && (github.base_ref == 'develop' || contains(github.base_ref, 'release-')) && github.event.pull_request.user.login != 'dependabot[bot]' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: "pip install 'towncrier>=18.6.0rc1'"
|
||||
@@ -207,40 +228,20 @@ jobs:
|
||||
env:
|
||||
PULL_REQUEST_NUMBER: ${{ github.event.number }}
|
||||
|
||||
lint-pydantic:
|
||||
runs-on: ubuntu-latest
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.linting == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
poetry-version: "2.1.1"
|
||||
extras: "all"
|
||||
- run: poetry run scripts-dev/check_pydantic_models.py
|
||||
|
||||
lint-clippy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
components: clippy
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
components: clippy
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: cargo clippy -- -D warnings
|
||||
|
||||
@@ -252,14 +253,14 @@ jobs:
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: nightly-2025-04-23
|
||||
components: clippy
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
toolchain: ${{ env.RUST_NIGHTLY_VERSION }}
|
||||
components: clippy
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: cargo clippy --all-features -- -D warnings
|
||||
|
||||
@@ -270,13 +271,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Setup Poetry
|
||||
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
@@ -284,7 +285,7 @@ jobs:
|
||||
# Install like a normal project from source with all optional dependencies
|
||||
extras: all
|
||||
install-project: "true"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
|
||||
- name: Ensure `Cargo.lock` is up to date (no stray changes after install)
|
||||
# The `::error::` syntax is using GitHub Actions' error annotations, see
|
||||
@@ -306,19 +307,36 @@ jobs:
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
# We use nightly so that we can use some unstable options that we use in
|
||||
# `.rustfmt.toml`.
|
||||
toolchain: nightly-2025-04-23
|
||||
toolchain: ${{ env.RUST_NIGHTLY_VERSION }}
|
||||
components: rustfmt
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: cargo fmt --check
|
||||
|
||||
lint-golangci:
|
||||
runs-on: ubuntu-latest
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.golangci == 'true' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
||||
with:
|
||||
cache-dependency-path: complement/go.sum
|
||||
go-version-file: complement/go.mod
|
||||
|
||||
- name: Run golangci-lint
|
||||
working-directory: ./complement
|
||||
run: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.1 run ./... --max-issues-per-linter=0
|
||||
|
||||
# This is to detect issues with the rst file, which can otherwise cause issues
|
||||
# when uploading packages to PyPi.
|
||||
lint-readme:
|
||||
@@ -326,8 +344,8 @@ jobs:
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.linting_readme == 'true' }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- run: "pip install rstcheck"
|
||||
@@ -341,7 +359,6 @@ jobs:
|
||||
- lint-mypy
|
||||
- lint-crlf
|
||||
- lint-newsfile
|
||||
- lint-pydantic
|
||||
- check-sampleconfig
|
||||
- check-schema-delta
|
||||
- check-lockfile
|
||||
@@ -349,6 +366,7 @@ jobs:
|
||||
- lint-clippy-nightly
|
||||
- lint-rust
|
||||
- lint-rustfmt
|
||||
- lint-golangci
|
||||
- lint-readme
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -363,21 +381,20 @@ jobs:
|
||||
lint
|
||||
lint-mypy
|
||||
lint-newsfile
|
||||
lint-pydantic
|
||||
lint-clippy
|
||||
lint-clippy-nightly
|
||||
lint-rust
|
||||
lint-rustfmt
|
||||
lint-golangci
|
||||
lint-readme
|
||||
|
||||
|
||||
calculate-test-jobs:
|
||||
if: ${{ !cancelled() && !failure() }} # Allow previous steps to be skipped, but not fail
|
||||
needs: linting-done
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- id: get-matrix
|
||||
@@ -394,10 +411,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
job: ${{ fromJson(needs.calculate-test-jobs.outputs.trial_test_matrix) }}
|
||||
job: ${{ fromJson(needs.calculate-test-jobs.outputs.trial_test_matrix) }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- run: sudo apt-get -qq install xmlsec1
|
||||
- name: Set up PostgreSQL ${{ matrix.job.postgres-version }}
|
||||
if: ${{ matrix.job.postgres-version }}
|
||||
@@ -415,12 +432,12 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: ${{ matrix.job.python-version }}
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
extras: ${{ matrix.job.extras }}
|
||||
- name: Await PostgreSQL
|
||||
if: ${{ matrix.job.postgres-version }}
|
||||
@@ -453,13 +470,13 @@ jobs:
|
||||
- changes
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
# There aren't wheels for some of the older deps, so we need to install
|
||||
# their build dependencies
|
||||
@@ -468,19 +485,17 @@ jobs:
|
||||
sudo apt-get -qq install build-essential libffi-dev python3-dev \
|
||||
libxml2-dev libxslt-dev xmlsec1 zlib1g-dev libjpeg-dev libwebp-dev
|
||||
|
||||
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: '3.9'
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Prepare old deps
|
||||
if: steps.cache-poetry-old-deps.outputs.cache-hit != 'true'
|
||||
run: .ci/scripts/prepare_old_deps.sh
|
||||
|
||||
# Note: we install using `pip` here, not poetry. `poetry install` ignores the
|
||||
# build-system section (https://github.com/python-poetry/poetry/issues/6154), but
|
||||
# we explicitly want to test that you can `pip install` using the oldest version
|
||||
# of poetry-core and setuptools-rust.
|
||||
- run: pip install .[all,test]
|
||||
# Note: we install using `uv` here, not poetry or pip to allow us to test with the
|
||||
# minimum version of all dependencies, both those explicitly specified and those
|
||||
# implicitly brought in by the explicit dependencies.
|
||||
run: |
|
||||
pip install uv
|
||||
uv pip install --system --resolution=lowest .[all,test]
|
||||
|
||||
# We nuke the local copy, as we've installed synapse into the virtualenv
|
||||
# (rather than use an editable install, which we no longer support). If we
|
||||
@@ -514,17 +529,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["pypy-3.9"]
|
||||
python-version: ["pypy-3.10"]
|
||||
extras: ["all"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
# Install libs necessary for PyPy to build binary wheels for dependencies
|
||||
- run: sudo apt-get -qq install xmlsec1 libxml2-dev libxslt-dev
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
extras: ${{ matrix.extras }}
|
||||
- run: poetry run trial --jobs=2 tests
|
||||
- name: Dump logs
|
||||
@@ -568,7 +583,7 @@ jobs:
|
||||
job: ${{ fromJson(needs.calculate-test-jobs.outputs.sytest_test_matrix) }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Prepare test blacklist
|
||||
run: cat sytest-blacklist .ci/worker-blacklist > synapse-blacklist-with-workers
|
||||
|
||||
@@ -576,7 +591,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Run SyTest
|
||||
run: /bootstrap.sh synapse
|
||||
@@ -585,7 +600,7 @@ jobs:
|
||||
if: ${{ always() }}
|
||||
run: /sytest/scripts/tap_to_gha.pl /logs/results.tap
|
||||
- name: Upload SyTest logs
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: Sytest Logs - ${{ job.status }} - (${{ join(matrix.job.*, ', ') }})
|
||||
@@ -615,11 +630,11 @@ jobs:
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- run: sudo apt-get -qq install xmlsec1 postgresql-client
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
extras: "postgres"
|
||||
- run: .ci/scripts/test_export_data_command.sh
|
||||
env:
|
||||
@@ -628,7 +643,6 @@ jobs:
|
||||
PGPASSWORD: postgres
|
||||
PGDATABASE: postgres
|
||||
|
||||
|
||||
portdb:
|
||||
if: ${{ !failure() && !cancelled() && needs.changes.outputs.integration == 'true'}} # Allow previous steps to be skipped, but not fail
|
||||
needs:
|
||||
@@ -638,10 +652,10 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python-version: "3.9"
|
||||
postgres-version: "13"
|
||||
- python-version: "3.10"
|
||||
postgres-version: "14"
|
||||
|
||||
- python-version: "3.13"
|
||||
- python-version: "3.14"
|
||||
postgres-version: "17"
|
||||
|
||||
services:
|
||||
@@ -659,7 +673,7 @@ jobs:
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Add PostgreSQL apt repository
|
||||
# We need a version of pg_dump that can handle the version of
|
||||
# PostgreSQL being tested against. The Ubuntu package repository lags
|
||||
@@ -673,7 +687,7 @@ jobs:
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
extras: "postgres"
|
||||
- run: .ci/scripts/test_synapse_port_db.sh
|
||||
id: run_tester_script
|
||||
@@ -683,7 +697,7 @@ jobs:
|
||||
PGPASSWORD: postgres
|
||||
PGDATABASE: postgres
|
||||
- name: "Upload schema differences"
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ failure() && !cancelled() && steps.run_tester_script.outcome == 'failure' }}
|
||||
with:
|
||||
name: Schema dumps
|
||||
@@ -693,90 +707,53 @@ jobs:
|
||||
schema_diff
|
||||
|
||||
complement:
|
||||
uses: ./.github/workflows/complement_tests.yml
|
||||
if: "${{ !failure() && !cancelled() && needs.changes.outputs.integration == 'true' }}"
|
||||
needs:
|
||||
- linting-done
|
||||
- changes
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arrangement: monolith
|
||||
database: SQLite
|
||||
|
||||
- arrangement: monolith
|
||||
database: Postgres
|
||||
|
||||
- arrangement: workers
|
||||
database: Postgres
|
||||
|
||||
steps:
|
||||
- name: Checkout synapse codebase
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: synapse
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
|
||||
- name: Prepare Complement's Prerequisites
|
||||
run: synapse/.ci/scripts/setup_complement_prerequisites.sh
|
||||
|
||||
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
cache-dependency-path: complement/go.sum
|
||||
go-version-file: complement/go.mod
|
||||
|
||||
# use p=1 concurrency as GHA boxes are underpowered and don't like running tons of synapses at once.
|
||||
- run: |
|
||||
set -o pipefail
|
||||
COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh -p 1 -json 2>&1 | synapse/.ci/scripts/gotestfmt
|
||||
shell: bash
|
||||
env:
|
||||
POSTGRES: ${{ (matrix.database == 'Postgres') && 1 || '' }}
|
||||
WORKERS: ${{ (matrix.arrangement == 'workers') && 1 || '' }}
|
||||
name: Run Complement Tests
|
||||
|
||||
cargo-test:
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
# We need to explicitly specify `!cancelled() && !failure()` as otherwise
|
||||
# GitHub will implicitly add `success()`, which will be `false` when any job
|
||||
# in `needs`, or its dependents, is skipped. Most notably, jobs like
|
||||
# `lint-readme`, a dependency of `linting-done`, are unlikely to run very
|
||||
# often - and would result in this job being skipped.
|
||||
if: ${{ !cancelled() && !failure() && needs.changes.outputs.rust == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linting-done
|
||||
- changes
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: cargo test
|
||||
|
||||
# We want to ensure that the cargo benchmarks still compile, which requires a
|
||||
# nightly compiler.
|
||||
cargo-bench:
|
||||
if: ${{ needs.changes.outputs.rust == 'true' }}
|
||||
# See `cargo-test` above for why we need to specify `!cancelled() && !failure()`.
|
||||
if: ${{ !cancelled() && !failure() && needs.changes.outputs.rust == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linting-done
|
||||
- changes
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: nightly-2022-12-01
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
toolchain: ${{ env.RUST_NIGHTLY_VERSION }}
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- run: cargo bench --no-run
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
# This field is case-sensitive.
|
||||
TARGET_STATUS: Needs info
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
# Only clone the script file we care about, instead of the whole repo.
|
||||
sparse-checkout: .ci/scripts/triage_labelled_issue.sh
|
||||
|
||||
@@ -12,10 +12,9 @@ on:
|
||||
twisted_ref:
|
||||
description: Commit, branch or tag to checkout from upstream Twisted.
|
||||
required: false
|
||||
default: 'trunk'
|
||||
default: "trunk"
|
||||
type: string
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
@@ -43,19 +42,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
extras: "all"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
- run: |
|
||||
poetry remove twisted
|
||||
poetry add --extras tls git+https://github.com/twisted/twisted.git#${{ inputs.twisted_ref || 'trunk' }}
|
||||
@@ -70,26 +69,25 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- run: sudo apt-get -qq install xmlsec1
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
extras: "all test"
|
||||
poetry-version: "2.1.1"
|
||||
poetry-version: "2.4.1"
|
||||
- run: |
|
||||
poetry remove twisted
|
||||
poetry add --extras tls git+https://github.com/twisted/twisted.git#trunk
|
||||
poetry install --no-interaction --extras "all test"
|
||||
- run: poetry run trial --jobs 2 tests
|
||||
|
||||
- name: Dump logs
|
||||
# Logs are most useful when the command fails, always include them.
|
||||
if: ${{ always() }}
|
||||
@@ -108,22 +106,22 @@ jobs:
|
||||
if: needs.check_repo.outputs.should_run_workflow == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# We're using debian:bullseye because it uses Python 3.9 which is our minimum supported Python version.
|
||||
# We're using bookworm because that's what Debian oldstable is at the time of writing.
|
||||
# This job is a canary to warn us about unreleased twisted changes that would cause problems for us if
|
||||
# they were to be released immediately. For simplicity's sake (and to save CI runners) we use the oldest
|
||||
# version, assuming that any incompatibilities on newer versions would also be present on the oldest.
|
||||
image: matrixdotorg/sytest-synapse:bullseye
|
||||
image: matrixdotorg/sytest-synapse:bookworm
|
||||
volumes:
|
||||
- ${{ github.workspace }}:/src
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Patch dependencies
|
||||
# Note: The poetry commands want to create a virtualenv in /src/.venv/,
|
||||
@@ -147,7 +145,7 @@ jobs:
|
||||
if: ${{ always() }}
|
||||
run: /sytest/scripts/tap_to_gha.pl /logs/results.tap
|
||||
- name: Upload SyTest logs
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: Sytest Logs - ${{ job.status }} - (${{ join(matrix.*, ', ') }})
|
||||
@@ -156,54 +154,11 @@ jobs:
|
||||
/logs/**/*.log*
|
||||
|
||||
complement:
|
||||
uses: ./.github/workflows/complement_tests.yml
|
||||
needs: check_repo
|
||||
if: "!failure() && !cancelled() && needs.check_repo.outputs.should_run_workflow == 'true'"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arrangement: monolith
|
||||
database: SQLite
|
||||
|
||||
- arrangement: monolith
|
||||
database: Postgres
|
||||
|
||||
- arrangement: workers
|
||||
database: Postgres
|
||||
|
||||
steps:
|
||||
- name: Run actions/checkout@v4 for synapse
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: synapse
|
||||
|
||||
- name: Prepare Complement's Prerequisites
|
||||
run: synapse/.ci/scripts/setup_complement_prerequisites.sh
|
||||
|
||||
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
cache-dependency-path: complement/go.sum
|
||||
go-version-file: complement/go.mod
|
||||
|
||||
# This step is specific to the 'Twisted trunk' test run:
|
||||
- name: Patch dependencies
|
||||
run: |
|
||||
set -x
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt-get install -yqq python3 pipx
|
||||
pipx install poetry==2.1.1
|
||||
|
||||
poetry remove -n twisted
|
||||
poetry add -n --extras tls git+https://github.com/twisted/twisted.git#trunk
|
||||
poetry lock
|
||||
working-directory: synapse
|
||||
|
||||
- run: |
|
||||
set -o pipefail
|
||||
TEST_ONLY_SKIP_DEP_HASH_VERIFICATION=1 POSTGRES=${{ (matrix.database == 'Postgres') && 1 || '' }} WORKERS=${{ (matrix.arrangement == 'workers') && 1 || '' }} COMPLEMENT_DIR=`pwd`/complement synapse/scripts-dev/complement.sh -json 2>&1 | synapse/.ci/scripts/gotestfmt
|
||||
shell: bash
|
||||
name: Run Complement Tests
|
||||
with:
|
||||
use_twisted_trunk: true
|
||||
|
||||
# open an issue if the build fails, so we know about it.
|
||||
open-issue:
|
||||
@@ -217,7 +172,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -35,6 +35,7 @@ __pycache__/
|
||||
/media_store/
|
||||
/uploads
|
||||
/homeserver-config-overrides.d
|
||||
tmp/
|
||||
|
||||
# For direnv users
|
||||
/.envrc
|
||||
@@ -53,6 +54,7 @@ __pycache__/
|
||||
!/.coveragerc
|
||||
/.coverage*
|
||||
/.mypy_cache/
|
||||
/.ruff_cache/
|
||||
/.tox
|
||||
/.tox-pg-container
|
||||
/build/
|
||||
|
||||
+1057
-1
File diff suppressed because it is too large.
Load diff
Generated
+135
-181
@@ -2,21 +2,6 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
@@ -28,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
@@ -38,33 +23,23 @@ version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
@@ -103,9 +78,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.10.1"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
@@ -194,6 +169,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
@@ -217,9 +198,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -232,9 +213,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -242,15 +223,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@@ -259,15 +240,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -276,21 +257,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.31"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -300,7 +281,6 @@ dependencies = [
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
@@ -341,12 +321,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.11"
|
||||
@@ -410,12 +384,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.3.1"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
|
||||
checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
@@ -625,9 +598,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_segmenter"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e185fc13b6401c138cf40db12b863b35f5edf31b88192a545857b41aeaf7d3d3"
|
||||
checksum = "38e30e593cf9c3ca2f51aa312eb347cd1ba95715e91a842ec3fc9058eab2af4b"
|
||||
dependencies = [
|
||||
"core_maths",
|
||||
"displaydoc",
|
||||
@@ -678,23 +651,6 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "2.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
@@ -711,6 +667,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
@@ -753,9 +718,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||
|
||||
[[package]]
|
||||
name = "lru-slab"
|
||||
@@ -769,30 +734,12 @@ version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.4"
|
||||
@@ -804,20 +751,11 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
@@ -837,12 +775,6 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
@@ -879,37 +811,34 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3"
|
||||
version = "0.25.1"
|
||||
version = "0.28.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a"
|
||||
checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indoc",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"once_cell",
|
||||
"portable-atomic",
|
||||
"pyo3-build-config",
|
||||
"pyo3-ffi",
|
||||
"pyo3-macros",
|
||||
"unindent",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-build-config"
|
||||
version = "0.25.1"
|
||||
version = "0.28.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598"
|
||||
checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-ffi"
|
||||
version = "0.25.1"
|
||||
version = "0.28.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c"
|
||||
checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pyo3-build-config",
|
||||
@@ -917,9 +846,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-log"
|
||||
version = "0.12.4"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45192e5e4a4d2505587e27806c7b710c231c40c56f3bfc19535d0bb25df52264"
|
||||
checksum = "f64083bd3a16a353d9d62335808e8e13d0552d2a2b83fdb084496192dcfa9fcd"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"log",
|
||||
@@ -928,9 +857,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros"
|
||||
version = "0.25.1"
|
||||
version = "0.28.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50"
|
||||
checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"pyo3-macros-backend",
|
||||
@@ -940,9 +869,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros-backend"
|
||||
version = "0.25.1"
|
||||
version = "0.28.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc"
|
||||
checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -953,12 +882,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pythonize"
|
||||
version = "0.25.0"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597907139a488b22573158793aa7539df36ae863eba300c75f3a0d65fc475e27"
|
||||
checksum = "0b79f670c9626c8b651c0581011b57b6ba6970bb69faf01a7c4c0cfc81c43f95"
|
||||
dependencies = [
|
||||
"pyo3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -983,9 +913,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quinn-proto"
|
||||
version = "0.11.12"
|
||||
version = "0.11.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
|
||||
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.3",
|
||||
@@ -1033,9 +963,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
@@ -1062,9 +992,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.3"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
|
||||
checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -1074,9 +1004,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.11"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -1085,15 +1015,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.23"
|
||||
version = "0.12.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
|
||||
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
@@ -1145,18 +1075,21 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.31"
|
||||
@@ -1195,9 +1128,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.4"
|
||||
version = "0.103.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
|
||||
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@@ -1248,6 +1181,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
@@ -1280,15 +1219,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.145"
|
||||
version = "1.0.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1391,6 +1330,7 @@ name = "synapse"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"base64",
|
||||
"blake2",
|
||||
"bytes",
|
||||
@@ -1400,6 +1340,7 @@ dependencies = [
|
||||
"http",
|
||||
"http-body-util",
|
||||
"icu_segmenter",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mime",
|
||||
@@ -1409,6 +1350,7 @@ dependencies = [
|
||||
"pythonize",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@@ -1438,9 +1380,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.13.2"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
||||
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
@@ -1489,19 +1431,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.47.1"
|
||||
version = "1.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
|
||||
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"socket2 0.6.0",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1544,9 +1483,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.6"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
|
||||
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bytes",
|
||||
@@ -1619,12 +1558,6 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unindent"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
@@ -1782,6 +1715,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
@@ -1800,6 +1739,15 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
@@ -1982,3 +1930,9 @@ dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
|
||||
+51
-193
@@ -1,4 +1,4 @@
|
||||
.. image:: ./docs/element_logo_white_bg.svg
|
||||
.. image:: https://github.com/element-hq/synapse/raw/develop/docs/element_logo_white_bg.svg
|
||||
:height: 60px
|
||||
|
||||
**Element Synapse - Matrix homeserver implementation**
|
||||
@@ -7,170 +7,48 @@
|
||||
|
||||
Synapse is an open source `Matrix <https://matrix.org>`__ homeserver
|
||||
implementation, written and maintained by `Element <https://element.io>`_.
|
||||
`Matrix <https://github.com/matrix-org>`__ is the open standard for
|
||||
secure and interoperable real-time communications. You can directly run
|
||||
and manage the source code in this repository, available under an AGPL
|
||||
license (or alternatively under a commercial license from Element).
|
||||
There is no support provided by Element unless you have a
|
||||
subscription from Element.
|
||||
`Matrix <https://github.com/matrix-org>`__ is the open standard for secure and
|
||||
interoperable real-time communications. You can directly run and manage the
|
||||
source code in this repository, available under an AGPL license (or
|
||||
alternatively under a commercial license from Element).
|
||||
|
||||
Subscription
|
||||
============
|
||||
There is no support provided by Element unless you have a subscription from
|
||||
Element.
|
||||
|
||||
For those that need an enterprise-ready solution, Element
|
||||
Server Suite (ESS) is `available via subscription <https://element.io/pricing>`_.
|
||||
ESS builds on Synapse to offer a complete Matrix-based backend including the full
|
||||
`Admin Console product <https://element.io/enterprise-functionality/admin-console>`_,
|
||||
giving admins the power to easily manage an organization-wide
|
||||
deployment. It includes advanced identity management, auditing,
|
||||
moderation and data retention options as well as Long-Term Support and
|
||||
SLAs. ESS supports any Matrix-compatible client.
|
||||
🚀 Getting started
|
||||
==================
|
||||
|
||||
.. contents::
|
||||
This component is developed and maintained by `Element <https://element.io>`_.
|
||||
It gets shipped as part of the **Element Server Suite (ESS)** which provides the
|
||||
official means of deployment.
|
||||
|
||||
🛠️ Installation and configuration
|
||||
==================================
|
||||
ESS is a Matrix distribution from Element with focus on quality and ease of use.
|
||||
It ships a full Matrix stack tailored to the respective use case.
|
||||
|
||||
The Synapse documentation describes `how to install Synapse <https://element-hq.github.io/synapse/latest/setup/installation.html>`_. We recommend using
|
||||
`Docker images <https://element-hq.github.io/synapse/latest/setup/installation.html#docker-images-and-ansible-playbooks>`_ or `Debian packages from Matrix.org
|
||||
<https://element-hq.github.io/synapse/latest/setup/installation.html#matrixorg-packages>`_.
|
||||
There are three editions of ESS:
|
||||
|
||||
.. _federation:
|
||||
|
||||
Synapse has a variety of `config options
|
||||
<https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html>`_
|
||||
which can be used to customise its behaviour after installation.
|
||||
There are additional details on how to `configure Synapse for federation here
|
||||
<https://element-hq.github.io/synapse/latest/federate.html>`_.
|
||||
|
||||
.. _reverse-proxy:
|
||||
|
||||
Using a reverse proxy with Synapse
|
||||
----------------------------------
|
||||
|
||||
It is recommended to put a reverse proxy such as
|
||||
`nginx <https://nginx.org/en/docs/http/ngx_http_proxy_module.html>`_,
|
||||
`Apache <https://httpd.apache.org/docs/current/mod/mod_proxy_http.html>`_,
|
||||
`Caddy <https://caddyserver.com/docs/quick-starts/reverse-proxy>`_,
|
||||
`HAProxy <https://www.haproxy.org/>`_ or
|
||||
`relayd <https://man.openbsd.org/relayd.8>`_ in front of Synapse. One advantage of
|
||||
doing so is that it means that you can expose the default https port (443) to
|
||||
Matrix clients without needing to run Synapse with root privileges.
|
||||
For information on configuring one, see `the reverse proxy docs
|
||||
<https://element-hq.github.io/synapse/latest/reverse_proxy.html>`_.
|
||||
|
||||
Upgrading an existing Synapse
|
||||
-----------------------------
|
||||
|
||||
The instructions for upgrading Synapse are in `the upgrade notes`_.
|
||||
Please check these instructions as upgrading may require extra steps for some
|
||||
versions of Synapse.
|
||||
|
||||
.. _the upgrade notes: https://element-hq.github.io/synapse/develop/upgrade.html
|
||||
- `ESS Community <https://github.com/element-hq/ess-helm>`_ - the free Matrix
|
||||
distribution from Element tailored to small-/mid-scale, non-commercial
|
||||
community use cases
|
||||
- `ESS Pro <https://element.io/server-suite>`_ - the commercial Matrix
|
||||
distribution from Element for professional use
|
||||
- `ESS TI-M <https://element.io/server-suite/ti-messenger>`_ - a special version
|
||||
of ESS Pro focused on the requirements of TI-Messenger Pro and ePA as
|
||||
specified by the German National Digital Health Agency Gematik
|
||||
|
||||
|
||||
Platform dependencies
|
||||
---------------------
|
||||
🛠️ Standalone installation and configuration
|
||||
============================================
|
||||
|
||||
Synapse uses a number of platform dependencies such as Python and PostgreSQL,
|
||||
and aims to follow supported upstream versions. See the
|
||||
`deprecation policy <https://element-hq.github.io/synapse/latest/deprecation_policy.html>`_
|
||||
for more details.
|
||||
The Synapse documentation describes `options for installing Synapse standalone
|
||||
<https://element-hq.github.io/synapse/latest/setup/installation.html>`_. See
|
||||
below for more useful documentation links.
|
||||
|
||||
- `Synapse configuration options <https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html>`_
|
||||
- `Synapse configuration for federation <https://element-hq.github.io/synapse/latest/federate.html>`_
|
||||
- `Using a reverse proxy with Synapse <https://element-hq.github.io/synapse/latest/reverse_proxy.html>`_
|
||||
- `Upgrading Synapse <https://element-hq.github.io/synapse/develop/upgrade.html>`_
|
||||
|
||||
Security note
|
||||
-------------
|
||||
|
||||
Matrix serves raw, user-supplied data in some APIs -- specifically the `content
|
||||
repository endpoints`_.
|
||||
|
||||
.. _content repository endpoints: https://matrix.org/docs/spec/client_server/latest.html#get-matrix-media-r0-download-servername-mediaid
|
||||
|
||||
Whilst we make a reasonable effort to mitigate against XSS attacks (for
|
||||
instance, by using `CSP`_), a Matrix homeserver should not be hosted on a
|
||||
domain hosting other web applications. This especially applies to sharing
|
||||
the domain with Matrix web clients and other sensitive applications like
|
||||
webmail. See
|
||||
https://developer.github.com/changes/2014-04-25-user-content-security for more
|
||||
information.
|
||||
|
||||
.. _CSP: https://github.com/matrix-org/synapse/pull/1021
|
||||
|
||||
Ideally, the homeserver should not simply be on a different subdomain, but on
|
||||
a completely different `registered domain`_ (also known as top-level site or
|
||||
eTLD+1). This is because `some attacks`_ are still possible as long as the two
|
||||
applications share the same registered domain.
|
||||
|
||||
.. _registered domain: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-2.3
|
||||
|
||||
.. _some attacks: https://en.wikipedia.org/wiki/Session_fixation#Attacks_using_cross-subdomain_cookie
|
||||
|
||||
To illustrate this with an example, if your Element Web or other sensitive web
|
||||
application is hosted on ``A.example1.com``, you should ideally host Synapse on
|
||||
``example2.com``. Some amount of protection is offered by hosting on
|
||||
``B.example1.com`` instead, so this is also acceptable in some scenarios.
|
||||
However, you should *not* host your Synapse on ``A.example1.com``.
|
||||
|
||||
Note that all of the above refers exclusively to the domain used in Synapse's
|
||||
``public_baseurl`` setting. In particular, it has no bearing on the domain
|
||||
mentioned in MXIDs hosted on that server.
|
||||
|
||||
Following this advice ensures that even if an XSS is found in Synapse, the
|
||||
impact to other applications will be minimal.
|
||||
|
||||
|
||||
🧪 Testing a new installation
|
||||
=============================
|
||||
|
||||
The easiest way to try out your new Synapse installation is by connecting to it
|
||||
from a web client.
|
||||
|
||||
Unless you are running a test instance of Synapse on your local machine, in
|
||||
general, you will need to enable TLS support before you can successfully
|
||||
connect from a client: see
|
||||
`TLS certificates <https://element-hq.github.io/synapse/latest/setup/installation.html#tls-certificates>`_.
|
||||
|
||||
An easy way to get started is to login or register via Element at
|
||||
https://app.element.io/#/login or https://app.element.io/#/register respectively.
|
||||
You will need to change the server you are logging into from ``matrix.org``
|
||||
and instead specify a homeserver URL of ``https://<server_name>:8448``
|
||||
(or just ``https://<server_name>`` if you are using a reverse proxy).
|
||||
If you prefer to use another client, refer to our
|
||||
`client breakdown <https://matrix.org/ecosystem/clients/>`_.
|
||||
|
||||
If all goes well you should at least be able to log in, create a room, and
|
||||
start sending messages.
|
||||
|
||||
.. _`client-user-reg`:
|
||||
|
||||
Registering a new user from a client
|
||||
------------------------------------
|
||||
|
||||
By default, registration of new users via Matrix clients is disabled. To enable
|
||||
it:
|
||||
|
||||
1. In the
|
||||
`registration config section <https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#registration>`_
|
||||
set ``enable_registration: true`` in ``homeserver.yaml``.
|
||||
2. Then **either**:
|
||||
|
||||
a. set up a `CAPTCHA <https://element-hq.github.io/synapse/latest/CAPTCHA_SETUP.html>`_, or
|
||||
b. set ``enable_registration_without_verification: true`` in ``homeserver.yaml``.
|
||||
|
||||
We **strongly** recommend using a CAPTCHA, particularly if your homeserver is exposed to
|
||||
the public internet. Without it, anyone can freely register accounts on your homeserver.
|
||||
This can be exploited by attackers to create spambots targeting the rest of the Matrix
|
||||
federation.
|
||||
|
||||
Your new Matrix ID will be formed partly from the ``server_name``, and partly
|
||||
from a localpart you specify when you create the account in the form of::
|
||||
|
||||
@localpart:my.domain.name
|
||||
|
||||
(pronounced "at localpart on my dot domain dot name").
|
||||
|
||||
As when logging in, you will need to specify a "Custom server". Specify your
|
||||
desired ``localpart`` in the 'Username' box.
|
||||
|
||||
🎯 Troubleshooting and support
|
||||
==============================
|
||||
@@ -182,7 +60,7 @@ Enterprise quality support for Synapse including SLAs is available as part of an
|
||||
`Element Server Suite (ESS) <https://element.io/pricing>`_ subscription.
|
||||
|
||||
If you are an existing ESS subscriber then you can raise a `support request <https://ems.element.io/support>`_
|
||||
and access the `knowledge base <https://ems-docs.element.io>`_.
|
||||
and access the `Element product documentation <https://docs.element.io>`_.
|
||||
|
||||
🤝 Community support
|
||||
--------------------
|
||||
@@ -201,35 +79,6 @@ issues for support requests, only for bug reports and feature requests.
|
||||
.. |docs| replace:: ``docs``
|
||||
.. _docs: docs
|
||||
|
||||
🪪 Identity Servers
|
||||
===================
|
||||
|
||||
Identity servers have the job of mapping email addresses and other 3rd Party
|
||||
IDs (3PIDs) to Matrix user IDs, as well as verifying the ownership of 3PIDs
|
||||
before creating that mapping.
|
||||
|
||||
**Identity servers do not store accounts or credentials - these are stored and managed on homeservers.
|
||||
Identity Servers are just for mapping 3rd Party IDs to Matrix IDs.**
|
||||
|
||||
This process is highly security-sensitive, as there is an obvious risk of spam if it
|
||||
is too easy to sign up for Matrix accounts or harvest 3PID data. In the longer
|
||||
term, we hope to create a decentralised system to manage it (`matrix-doc #712
|
||||
<https://github.com/matrix-org/matrix-doc/issues/712>`_), but in the meantime,
|
||||
the role of managing trusted identity in the Matrix ecosystem is farmed out to
|
||||
a cluster of known trusted ecosystem partners, who run 'Matrix Identity
|
||||
Servers' such as `Sydent <https://github.com/matrix-org/sydent>`_, whose role
|
||||
is purely to authenticate and track 3PID logins and publish end-user public
|
||||
keys.
|
||||
|
||||
You can host your own copy of Sydent, but this will prevent you reaching other
|
||||
users in the Matrix ecosystem via their email address, and prevent them finding
|
||||
you. We therefore recommend that you use one of the centralised identity servers
|
||||
at ``https://matrix.org`` or ``https://vector.im`` for now.
|
||||
|
||||
To reiterate: the Identity server will only be used if you choose to associate
|
||||
an email address with your account, or send an invite to another user via their
|
||||
email address.
|
||||
|
||||
|
||||
🛠️ Development
|
||||
==============
|
||||
@@ -252,20 +101,29 @@ Alongside all that, join our developer community on Matrix:
|
||||
Copyright and Licensing
|
||||
=======================
|
||||
|
||||
| Copyright 2014-2017 OpenMarket Ltd
|
||||
| Copyright 2017 Vector Creations Ltd
|
||||
| Copyright 2017-2025 New Vector Ltd
|
||||
|
|
||||
| Copyright 2014–2017 OpenMarket Ltd
|
||||
| Copyright 2017 Vector Creations Ltd
|
||||
| Copyright 2017–2025 New Vector Ltd
|
||||
| Copyright 2025 Element Creations Ltd
|
||||
|
||||
This software is dual-licensed by New Vector Ltd (Element). It can be used either:
|
||||
This software is dual-licensed by Element Creations Ltd (Element). It can be
|
||||
used either:
|
||||
|
||||
(1) for free under the terms of the GNU Affero General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
|
||||
(1) for free under the terms of the GNU Affero General Public License (as
|
||||
published by the Free Software Foundation, either version 3 of the License,
|
||||
or (at your option) any later version); OR
|
||||
|
||||
(2) under the terms of a paid-for Element Commercial License agreement between you and Element (the terms of which may vary depending on what you and Element have agreed to).
|
||||
(2) under the terms of a paid-for Element Commercial License agreement between
|
||||
you and Element (the terms of which may vary depending on what you and
|
||||
Element have agreed to).
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the Licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses.
|
||||
Unless required by applicable law or agreed to in writing, software distributed
|
||||
under the Licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the
|
||||
specific language governing permissions and limitations under the Licenses.
|
||||
|
||||
Please contact `licensing@element.io <mailto:licensing@element.io>`_ to purchase an Element commercial license for this software.
|
||||
Please contact `licensing@element.io <mailto:licensing@element.io>`_ to purchase
|
||||
an Element commercial license for this software.
|
||||
|
||||
|
||||
.. |support| image:: https://img.shields.io/badge/matrix-community%20support-success
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
title = "Synapse"
|
||||
authors = ["The Matrix.org Foundation C.I.C."]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
|
||||
# The directory that documentation files are stored in
|
||||
src = "docs"
|
||||
@@ -31,13 +30,10 @@ site-url = "/synapse/"
|
||||
# Additional HTML, JS, CSS that's injected into each page of the book.
|
||||
# More information available in docs/website_files/README.md
|
||||
additional-css = [
|
||||
"docs/website_files/table-of-contents.css",
|
||||
"docs/website_files/remove-nav-buttons.css",
|
||||
"docs/website_files/indent-section-headers.css",
|
||||
"docs/website_files/version-picker.css",
|
||||
]
|
||||
additional-js = [
|
||||
"docs/website_files/table-of-contents.js",
|
||||
"docs/website_files/version-picker.js",
|
||||
"docs/website_files/version.js",
|
||||
]
|
||||
|
||||
+5
-5
@@ -2,13 +2,13 @@
|
||||
|
||||
import itertools
|
||||
import os
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from setuptools_rust import Binding, RustExtension
|
||||
|
||||
|
||||
def build(setup_kwargs: Dict[str, Any]) -> None:
|
||||
def build(setup_kwargs: dict[str, Any]) -> None:
|
||||
original_project_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
cargo_toml_path = os.path.join(original_project_dir, "rust", "Cargo.toml")
|
||||
|
||||
@@ -27,12 +27,12 @@ def build(setup_kwargs: Dict[str, Any]) -> None:
|
||||
setup_kwargs["zip_safe"] = False
|
||||
|
||||
# We look up the minimum supported Python version with
|
||||
# `python_requires` (e.g. ">=3.9.0,<4.0.0") and finding the first Python
|
||||
# `python_requires` (e.g. ">=3.10.0,<4.0.0") and finding the first Python
|
||||
# version that matches. We then convert that into the `py_limited_api` form,
|
||||
# e.g. cp39 for Python 3.9.
|
||||
# e.g. cp310 for Python 3.10.
|
||||
py_limited_api: str
|
||||
python_bounds = SpecifierSet(setup_kwargs["python_requires"])
|
||||
for minor_version in itertools.count(start=8):
|
||||
for minor_version in itertools.count(start=10):
|
||||
if f"3.{minor_version}.0" in python_bounds:
|
||||
py_limited_api = f"cp3{minor_version}"
|
||||
break
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Change default room version to 11, implementing [MSC4239](https://github.com/matrix-org/matrix-spec-proposals/pull/4239) as part of Matrix v1.14.
|
||||
@@ -0,0 +1 @@
|
||||
Add animation support to the media thumbnailer, gated behind the `animated` query parameter on the thumbnail endpoint (defaults to off).
|
||||
@@ -0,0 +1 @@
|
||||
Return `M_USER_LIMIT_EXCEEDED` error code for media upload limits from [MSC4335](https://github.com/matrix-org/matrix-spec-proposals/pull/4335).
|
||||
@@ -1 +0,0 @@
|
||||
Allow using [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190) behavior without the opt-in registration flag. Contributed by @tulir @ Beeper.
|
||||
@@ -1 +0,0 @@
|
||||
Stabilized support for [MSC4326](https://github.com/matrix-org/matrix-spec-proposals/pull/4326): Device masquerading for appservices. Contributed by @tulir @ Beeper.
|
||||
@@ -1 +0,0 @@
|
||||
Move `start_doing_background_updates()` to `HomeServer.start_background_tasks()`.
|
||||
@@ -1 +0,0 @@
|
||||
Move unique snowflake homeserver background tasks to `start_background_tasks` (the standard pattern for this kind of thing).
|
||||
@@ -1 +0,0 @@
|
||||
Drop a deprecated field of the `PyGitHub` dependency in the release script and raise the dependency's minimum version to `1.59.0`.
|
||||
@@ -1 +0,0 @@
|
||||
Update TODO list of conflicting areas where we encounter metrics being clobbered (`ApplicationService`).
|
||||
@@ -0,0 +1,3 @@
|
||||
Fix third-party (3pid) invites over federation failing intermittently in version 12 rooms, whose room IDs no longer encode a server name. ([#19898](https://github.com/element-hq/synapse/issues/19898))
|
||||
|
||||
Fix `/createRoom` intermittently failing with a 500 error in version 12 rooms when the same user creates several rooms at once, due to colliding room IDs.
|
||||
@@ -0,0 +1 @@
|
||||
Update release script JSON schema find/replace task to be compatible with macOS.
|
||||
@@ -0,0 +1 @@
|
||||
Clarify the usage of the `guests` parameter when using the List user API with the Matrix Authentication Service integration enabled.
|
||||
@@ -0,0 +1 @@
|
||||
Fix server key cache invalidations being silently dropped on workers.
|
||||
@@ -0,0 +1 @@
|
||||
Remove alert silencing deploy step from release script instructions as it's no longer necessary.
|
||||
@@ -0,0 +1 @@
|
||||
Link to changelog instead of duplicating content in the tag/release.
|
||||
@@ -0,0 +1 @@
|
||||
Fix `HomeServer.shutdown()` not being able to cleanly shutdown the homeserver (caused by Rust code referencing Python `DatabasePool`).
|
||||
@@ -0,0 +1,38 @@
|
||||
# Docs: https://golangci-lint.run/docs/configuration/file/
|
||||
#
|
||||
# Go formatting/linting rules
|
||||
#
|
||||
# This is run as part of the normal linting utility script,
|
||||
# `poetry run ./scripts-dev/lint.sh`
|
||||
|
||||
version: "2"
|
||||
|
||||
linters:
|
||||
# Default set of linters.
|
||||
# The value can be:
|
||||
# - `standard`: https://golangci-lint.run/docs/linters/#enabled-by-default
|
||||
# - `all`: enables all linters by default.
|
||||
# - `none`: disables all linters by default.
|
||||
# - `fast`: enables only linters considered as "fast" (`golangci-lint help linters --json | jq '[ .[] | select(.fast==true) ] | map(.name)'`).
|
||||
# Default: standard
|
||||
default: standard
|
||||
|
||||
# Enable specific linter.
|
||||
# enable:
|
||||
# - example
|
||||
|
||||
# Disable specific linters.
|
||||
disable:
|
||||
# FIXME: Ideally, we'd enable the `bodyclose` lint but there are many
|
||||
# false-positives (like https://github.com/timakin/bodyclose/issues/39) and just is
|
||||
# not well-suited for our use case (https://github.com/timakin/bodyclose/issues/11 and
|
||||
# https://github.com/timakin/bodyclose/issues/76).
|
||||
- bodyclose
|
||||
|
||||
formatters:
|
||||
# Enable specific formatter.
|
||||
# Default: [] (uses standard Go formatting)
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
- golines
|
||||
@@ -0,0 +1,95 @@
|
||||
# Complement testing
|
||||
|
||||
Complement is a black box integration testing framework for Matrix homeservers. It
|
||||
allows us to write end-to-end tests that interact with real Synapse homeservers to
|
||||
ensure everything works at a holistic level.
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
Nothing beyond a [normal Complement
|
||||
setup](https://github.com/matrix-org/complement#running) (just Go and Docker).
|
||||
|
||||
|
||||
## Running tests
|
||||
|
||||
Run tests from the [Complement](https://github.com/matrix-org/complement) repo:
|
||||
|
||||
```shell
|
||||
# Run the tests
|
||||
./scripts-dev/complement.sh
|
||||
|
||||
# To run a whole group of tests, you can specify part of the test path:
|
||||
scripts-dev/complement.sh ./tests/csapi/... -run TestRoomCreate
|
||||
# To run a specific test, you can specify the whole name structure:
|
||||
scripts-dev/complement.sh ./tests/csapi/... -run TestRoomCreate/Parallel/POST_/createRoom_makes_a_public_room
|
||||
# Generally though, the `-run` parameter accepts regex patterns, so you can match however you like:
|
||||
scripts-dev/complement.sh ./tests/... -run 'TestRoomCreate/Parallel/POST_/createRoom_makes_a_(.*)'
|
||||
```
|
||||
|
||||
It's often nice to develop on Synapse and write Complement tests at the same time.
|
||||
Here is how to run your local Synapse checkout against your local Complement checkout.
|
||||
|
||||
```shell
|
||||
# To run a specific test
|
||||
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh ./tests/csapi/... -run TestRoomCreate
|
||||
```
|
||||
|
||||
The above will run a monolithic (single-process) Synapse with SQLite as the database.
|
||||
For other configurations, try:
|
||||
|
||||
- Passing `POSTGRES=1` as an environment variable to use the Postgres database instead.
|
||||
- Passing `WORKERS=1` as an environment variable to use a workerised setup instead. This
|
||||
option implies the use of Postgres.
|
||||
- If setting `WORKERS=1`, optionally set `WORKER_TYPES=` to declare which worker types
|
||||
you wish to test. A simple comma-delimited string containing the worker types
|
||||
defined from the `WORKERS_CONFIG` template in
|
||||
[here](https://github.com/element-hq/synapse/blob/develop/docker/configure_workers_and_start.py#L54).
|
||||
A safe example would be `WORKER_TYPES="federation_inbound, federation_sender,
|
||||
synchrotron"`. See the [worker documentation](../workers.md) for additional
|
||||
information on workers.
|
||||
- Passing `ASYNCIO_REACTOR=1` as an environment variable to use the asyncio-backed
|
||||
reactor with Twisted instead of the default one.
|
||||
- Passing `PODMAN=1` will use the [podman](https://podman.io/) container runtime,
|
||||
instead of docker.
|
||||
- Passing `UNIX_SOCKETS=1` will utilise Unix socket functionality for Synapse, Redis,
|
||||
and Postgres(when applicable).
|
||||
|
||||
To increase the log level for the tests, set `SYNAPSE_TEST_LOG_LEVEL`, e.g:
|
||||
```sh
|
||||
SYNAPSE_TEST_LOG_LEVEL=DEBUG COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestRoomCreate
|
||||
```
|
||||
|
||||
|
||||
### Running in-repo tests
|
||||
|
||||
In-repo Complement tests are tests that are vendored into this project. We use the
|
||||
in-repo test suite to test Synapse specific behaviors like the admin API.
|
||||
|
||||
To run the in-repo Complement tests, use the `--in-repo` command line argument.
|
||||
|
||||
```shell
|
||||
# Run only a specific test package.
|
||||
# Note: test packages are relative to the `./complement` directory in this project
|
||||
./scripts-dev/complement.sh --in-repo ./tests/...
|
||||
|
||||
# Similarly, you can also use `-run` to specify all or part of a specific test path to run
|
||||
scripts-dev/complement.sh --in-repo ./tests/... -run TestIntraShardFederation
|
||||
```
|
||||
|
||||
### Access database for homeserver after Complement test runs.
|
||||
|
||||
If you're curious what the database looks like after you run some tests, here are some
|
||||
steps to get you going in Synapse:
|
||||
|
||||
1. In your Complement test comment out `defer deployment.Destroy(t)` and replace with
|
||||
`defer time.Sleep(2 * time.Hour)` to keep the homeserver running after the tests
|
||||
complete
|
||||
1. Start the Complement tests
|
||||
1. Find the name of the container, `docker ps -f name=complement_` (this will filter for
|
||||
just the Complement related Docker containers)
|
||||
1. Access the container replacing the name with what you found in the previous step:
|
||||
`docker exec -it complement_1_hs_with_application_service.hs1_2 /bin/bash`
|
||||
1. Install sqlite (database driver), `apt-get update && apt-get install -y sqlite3`
|
||||
1. Then run `sqlite3` and open the database `.open /conf/homeserver.db` (this db path
|
||||
comes from the Synapse homeserver.yaml)
|
||||
@@ -0,0 +1,60 @@
|
||||
module github.com/element-hq/synapse
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/matrix-org/complement v0.0.0-20251120181401-44111a2a8a9d
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250813150445-9f5070a65744
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/docker/docker v28.3.3+incompatible
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/hashicorp/go-set/v3 v3.0.0 // indirect
|
||||
github.com/moby/sys/atomicwriter v0.1.0 // indirect
|
||||
github.com/oleiade/lane/v2 v2.0.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
gotest.tools/v3 v3.4.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 // indirect
|
||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
golang.org/x/crypto v0.52.0 // indirect
|
||||
golang.org/x/net v0.55.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.42.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,185 @@
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
||||
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/go-set/v3 v3.0.0 h1:CaJBQvQCOWoftrBcDt7Nwgo0kdpmrKxar/x2o6pV9JA=
|
||||
github.com/hashicorp/go-set/v3 v3.0.0/go.mod h1:IEghM2MpE5IaNvL+D7X480dfNtxjRXZ6VMpK3C8s2ok=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/matrix-org/complement v0.0.0-20251120181401-44111a2a8a9d h1:s2Xc9GB2E/pXdElP18h8+04Y3SmhaII7xh2YmCM7oZc=
|
||||
github.com/matrix-org/complement v0.0.0-20251120181401-44111a2a8a9d/go.mod h1:HioTV089DHLBfljH9QLGifJRE4Avnyk08BXXhCwd4gs=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250813150445-9f5070a65744 h1:5GvC2FD9O/PhuyY95iJQdNYHbDioEhMWdeMP9maDUL8=
|
||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20250813150445-9f5070a65744/go.mod h1:b6KVfDjXjA5Q7vhpOaMqIhFYvu5BuFVZixlNeTV/CLc=
|
||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4=
|
||||
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
|
||||
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/oleiade/lane/v2 v2.0.0 h1:XW/ex/Inr+bPkLd3O240xrFOhUkTd4Wy176+Gv0E3Qw=
|
||||
github.com/oleiade/lane/v2 v2.0.0/go.mod h1:i5FBPFAYSWCgLh58UkUGCChjcCzef/MI7PlQm2TKCeg=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/shoenig/test v1.11.0 h1:NoPa5GIoBwuqzIviCrnUJa+t5Xb4xi5Z+zODJnIDsEQ=
|
||||
github.com/shoenig/test v1.11.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
|
||||
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
|
||||
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
@@ -0,0 +1,187 @@
|
||||
package synapse_tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/complement"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/matrix-org/complement/b"
|
||||
"github.com/matrix-org/complement/federation"
|
||||
"github.com/matrix-org/complement/helpers"
|
||||
"github.com/matrix-org/complement/must"
|
||||
)
|
||||
|
||||
// This test verifies that events sent into a room between a /make_join and
|
||||
// /send_join are not lost to the joining server. When an event is created
|
||||
// during the join handshake, the join event's prev_events (set at make_join
|
||||
// time) won't reference it, creating two forward extremities. The server
|
||||
// handling the join should ensure the joining server can discover the missed
|
||||
// event, for example by sending a follow-up event that references both
|
||||
// extremities, prompting the joining server to backfill.
|
||||
//
|
||||
// See https://github.com/element-hq/synapse/pull/19390
|
||||
//
|
||||
// This test lives as a in-repo Synapse Complement test because the spec doesn't mandate
|
||||
// which events should be resolvable after the `/make_join`/`/send_join` dance (or that
|
||||
// a homeserver should send `m.dummy` events to tie things together).
|
||||
//
|
||||
// To be clear, resolving the events in the `/make_join`/`/send_join` gap would happen
|
||||
// naturally as soon as someone else sends an event who is on a homeserver aware of the
|
||||
// events in the gap (tie it into the DAG). The goal of the automatic dummy events is to
|
||||
// make this happen more immediately by sending a `m.dummy` event that ties things in
|
||||
// instead of waiting for another event to be sent naturally.
|
||||
func TestEventBetweenMakeJoinAndSendJoinIsNotLost(t *testing.T) {
|
||||
deployment := complement.Deploy(t, 1)
|
||||
defer deployment.Destroy(t)
|
||||
|
||||
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
|
||||
|
||||
// We track the message event ID sent between make_join and send_join.
|
||||
// After send_join, we wait for hs1 to send us either:
|
||||
// - the message event itself, or
|
||||
// - any event whose prev_events reference the message (e.g. a dummy event)
|
||||
//
|
||||
// atomic.Value is used because messageEventID is written on the main goroutine and
|
||||
// read on the HTTP handler goroutine, and needs synchronization (without
|
||||
// synchronization, writes are not guaranteed to be observed by other goroutines)
|
||||
var messageEventID atomic.Value
|
||||
messageEventID.Store("")
|
||||
messageDiscoverableWaiter := helpers.NewWaiter()
|
||||
|
||||
srv := federation.NewServer(t, deployment,
|
||||
// hs1 fetches our signing keys via /_matrix/key/v2/server to verify our
|
||||
// identity before accepting federation requests. Without this handler,
|
||||
// make_join is rejected with 401 M_UNAUTHORIZED.
|
||||
federation.HandleKeyRequests(),
|
||||
)
|
||||
// After send_join, hs1 will start sending us federation transactions via
|
||||
// /_matrix/federation/v1/send/{txnID}. Since we handle /send manually
|
||||
// below, any other requests (e.g. key fetches) that arrive unexpectedly
|
||||
// should be tolerated rather than treated as test failures.
|
||||
srv.UnexpectedRequestsAreErrors = false
|
||||
|
||||
// Custom /send handler: hs1 will push new room events to us via federation
|
||||
// transactions once we've joined. We use a raw handler because the
|
||||
// Complement server is not fully in the room until send_join completes, so
|
||||
// we can't use HandleTransactionRequests (which requires the room in
|
||||
// srv.rooms). Instead we parse the raw transaction body ourselves.
|
||||
srv.Mux().
|
||||
Handle("/_matrix/federation/v1/send/{transactionID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
body, err := io.ReadAll(req.Body)
|
||||
must.NotError(t, "failed to read request body in /send handler: %v", err)
|
||||
txn := gjson.ParseBytes(body)
|
||||
txn.Get("pdus").ForEach(func(_, pdu gjson.Result) bool {
|
||||
eventID := pdu.Get("event_id").String()
|
||||
eventType := pdu.Get("type").String()
|
||||
t.Logf("Received PDU via /send: type=%s id=%s", eventType, eventID)
|
||||
|
||||
// messageEventID is set after make_join but before send_join.
|
||||
// Transactions can arrive before that window, so skip PDUs that
|
||||
// arrive before we know which event to look for.
|
||||
msgID, _ := messageEventID.Load().(string)
|
||||
if msgID == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if this IS the message event (server pushed it directly).
|
||||
if eventID == msgID {
|
||||
messageDiscoverableWaiter.Finish()
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if this event's prev_events directly reference the message (e.g. a dummy
|
||||
// event tying the two forward extremities together). If so, the joining server
|
||||
// can backfill from that event and will discover the message.
|
||||
//
|
||||
// XXX: We only check one level of prev_events: if the reference is deeper in the
|
||||
// DAG, it's valid and the joining server can still reach the message through
|
||||
// backfill but our checks don't account for that yet (feel free to edit this
|
||||
// assertion if you run into this)
|
||||
pdu.Get("prev_events").ForEach(func(_, prevEvent gjson.Result) bool {
|
||||
if prevEvent.String() == msgID {
|
||||
messageDiscoverableWaiter.Finish()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return true
|
||||
})
|
||||
w.WriteHeader(200)
|
||||
// Respond with an empty PDU error map, which is the federation /send
|
||||
// success response format: each key would be a PDU ID whose processing
|
||||
// failed; an empty object means all PDUs were accepted.
|
||||
_, err = w.Write([]byte(`{"pdus":{}}`))
|
||||
must.NotError(t, "failed to write response body in /send handler: %v", err)
|
||||
})).
|
||||
Methods("PUT")
|
||||
|
||||
cancel := srv.Listen()
|
||||
defer cancel()
|
||||
|
||||
// Alice creates a room on hs1.
|
||||
roomID := alice.MustCreateRoom(t, map[string]interface{}{
|
||||
"preset": "public_chat",
|
||||
})
|
||||
|
||||
charlie := srv.UserID("charlie")
|
||||
origin := srv.ServerName()
|
||||
fedClient := srv.FederationClient(deployment)
|
||||
|
||||
// Step 1: make_join, hs1 returns a join event template whose prev_events
|
||||
// reflect the current room DAG tips.
|
||||
makeJoinResp, err := fedClient.MakeJoin(
|
||||
context.Background(), origin,
|
||||
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
|
||||
roomID, charlie,
|
||||
)
|
||||
must.NotError(t, "MakeJoin", err)
|
||||
|
||||
// Step 2: Alice sends a message on hs1. This advances the DAG past the
|
||||
// point captured by make_join's prev_events. The Complement server is not
|
||||
// yet in the room, so it won't receive this event via normal federation.
|
||||
messageEventID.Store(alice.SendEventSynced(t, roomID, b.Event{
|
||||
Type: "m.room.message",
|
||||
Content: map[string]interface{}{
|
||||
"msgtype": "m.text",
|
||||
"body": "Message sent between make_join and send_join",
|
||||
},
|
||||
}))
|
||||
t.Logf("Alice sent message %s between make_join and send_join", messageEventID.Load())
|
||||
|
||||
// Step 3: Build and sign the join event, then send_join.
|
||||
// The join event's prev_events are from step 1 (before the message),
|
||||
// so persisting it on hs1 creates two forward extremities: the message
|
||||
// and the join.
|
||||
verImpl, err := gomatrixserverlib.GetRoomVersion(makeJoinResp.RoomVersion)
|
||||
must.NotError(t, "GetRoomVersion", err)
|
||||
eb := verImpl.NewEventBuilderFromProtoEvent(&makeJoinResp.JoinEvent)
|
||||
joinEvent, err := eb.Build(time.Now(), srv.ServerName(), srv.KeyID, srv.Priv)
|
||||
must.NotError(t, "Build join event", err)
|
||||
|
||||
_, err = fedClient.SendJoin(
|
||||
context.Background(), origin,
|
||||
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
|
||||
joinEvent,
|
||||
)
|
||||
must.NotError(t, "SendJoin", err)
|
||||
|
||||
// Step 4: hs1 should make the missed message discoverable to the joining
|
||||
// server. We accept either receiving the message event directly, or
|
||||
// receiving any event whose prev_events reference it (allowing the
|
||||
// joining server to backfill).
|
||||
messageDiscoverableWaiter.Waitf(t, 5*time.Second,
|
||||
"Timed out waiting for message event %s to become discoverable — "+
|
||||
"the event sent between make_join and send_join was lost to the "+
|
||||
"joining server", messageEventID.Load(),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
//
|
||||
// Copyright (C) 2026 Element Creations Ltd
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// See the GNU Affero General Public License for more details:
|
||||
// <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
|
||||
package synapse_tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/complement"
|
||||
"github.com/matrix-org/complement/client"
|
||||
"github.com/matrix-org/complement/helpers"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// Stub test to ensure that homeservers can communicate with each other (federation works correctly).
|
||||
//
|
||||
// TODO: This test will disappear once we have other real Synapse specific tests in
|
||||
// place. This is simply here as an example without bloating the PR with some specific
|
||||
// new tests.
|
||||
func TestFederation(t *testing.T) {
|
||||
// Create two homeservers
|
||||
deployment := complement.Deploy(t, 2)
|
||||
defer deployment.Destroy(t)
|
||||
|
||||
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
|
||||
bob := deployment.Register(t, "hs2", helpers.RegistrationOpts{})
|
||||
|
||||
aliceRoomID := alice.MustCreateRoom(t, map[string]any{
|
||||
"preset": "public_chat",
|
||||
})
|
||||
bobRoomID := bob.MustCreateRoom(t, map[string]any{
|
||||
"preset": "public_chat",
|
||||
})
|
||||
|
||||
t.Run("parallel", func(t *testing.T) {
|
||||
t.Run("HS1 -> HS2", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
alice.MustJoinRoom(t, bobRoomID, []spec.ServerName{
|
||||
deployment.GetFullyQualifiedHomeserverName(t, "hs2"),
|
||||
})
|
||||
|
||||
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, bobRoomID))
|
||||
})
|
||||
|
||||
t.Run("HS2 -> HS1", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
bob.MustJoinRoom(t, aliceRoomID, []spec.ServerName{
|
||||
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
|
||||
})
|
||||
|
||||
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, aliceRoomID))
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dockerutil
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
// Write `data` as a file into a container at the given `path`.
|
||||
//
|
||||
// Internally, produces an uncompressed single-file tape archive (tar) that is sent to the docker
|
||||
// daemon to be unpacked into the container filesystem.
|
||||
func WriteFileIntoContainer(
|
||||
t *testing.T,
|
||||
docker *client.Client,
|
||||
containerID string,
|
||||
path string,
|
||||
data []byte,
|
||||
) error {
|
||||
// Create a fake/virtual tar file in memory that we can copy to the container
|
||||
// via https://stackoverflow.com/a/52131297/796832
|
||||
var buf bytes.Buffer
|
||||
tw := tar.NewWriter(&buf)
|
||||
err := tw.WriteHeader(&tar.Header{
|
||||
Name: path,
|
||||
Mode: 0777,
|
||||
Size: int64(len(data)),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"WriteIntoContainer: failed to write tarball header for %s: %v",
|
||||
path,
|
||||
err,
|
||||
)
|
||||
}
|
||||
_, err = tw.Write([]byte(data))
|
||||
if err != nil {
|
||||
return fmt.Errorf("WriteIntoContainer: failed to write tarball data for %s: %w", path, err)
|
||||
}
|
||||
|
||||
err = tw.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"WriteIntoContainer: failed to close tarball writer for %s: %w",
|
||||
path,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
// Put our new fake file in the container volume
|
||||
err = docker.CopyToContainer(
|
||||
t.Context(),
|
||||
containerID,
|
||||
"/",
|
||||
&buf,
|
||||
container.CopyToContainerOptions{
|
||||
AllowOverwriteDirWithFile: false,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("WriteIntoContainer: failed to copy: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
//
|
||||
// Copyright (C) 2026 Element Creations Ltd
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// See the GNU Affero General Public License for more details:
|
||||
// <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
|
||||
package synapse_tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/complement"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
complement.TestMain(m, "synapse")
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
//
|
||||
// Copyright (C) 2026 Element Creations Ltd
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// See the GNU Affero General Public License for more details:
|
||||
// <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
|
||||
package synapse_tests
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dockerClient "github.com/docker/docker/client"
|
||||
"github.com/element-hq/synapse/tests/internal/dockerutil"
|
||||
"github.com/matrix-org/complement"
|
||||
"github.com/matrix-org/complement/client"
|
||||
"github.com/matrix-org/complement/match"
|
||||
"github.com/matrix-org/complement/must"
|
||||
)
|
||||
|
||||
const OIDC_HOMESERVER_CONFIG string = `
|
||||
oidc_providers:
|
||||
- idp_id: "test_provider"
|
||||
idp_name: "Test OIDC Provider"
|
||||
issuer: "https://example.invalid"
|
||||
client_id: "test_client_id"
|
||||
client_secret: "test_secret"
|
||||
scopes: ["openid"]
|
||||
discover: true
|
||||
user_mapping_provider:
|
||||
module: "synapse.handlers.oidc.JinjaOidcMappingProvider"
|
||||
config:
|
||||
display_name_template: "{{ user.given_name }}"
|
||||
email_template: "{{ user.email }}"
|
||||
`
|
||||
|
||||
// Test that Synapse still starts up when configured with an OIDC provider that is unavailable.
|
||||
//
|
||||
// This is a regression test: Synapse previously would fail to start up
|
||||
// at all if the OIDC provider was down on startup.
|
||||
// https://github.com/element-hq/synapse/issues/8088
|
||||
//
|
||||
// Now instead of failing to start, Synapse will produce a 503 response on the
|
||||
// `/_matrix/client/v3/login/sso/redirect/oidc-test_provider` endpoint.
|
||||
func TestOIDCProviderUnavailable(t *testing.T) {
|
||||
// Deploy a single homeserver
|
||||
//
|
||||
// FIXME: Since we're modifying the homeserver config, this should be using a clean
|
||||
// deploy that won't affect subsequent tests because Complement will re-use the
|
||||
// deployment, see https://github.com/element-hq/synapse/issues/19937
|
||||
deployment := complement.Deploy(t, 1)
|
||||
defer deployment.Destroy(t)
|
||||
|
||||
// Get Docker client to manipulate container
|
||||
dc, err := dockerClient.NewClientWithOpts(
|
||||
dockerClient.FromEnv,
|
||||
dockerClient.WithAPIVersionNegotiation(),
|
||||
)
|
||||
must.NotError(t, "failed creating docker client", err)
|
||||
|
||||
// Configure the OIDC Provider by writing a config fragment
|
||||
err = dockerutil.WriteFileIntoContainer(
|
||||
t,
|
||||
dc,
|
||||
deployment.ContainerID(t, "hs1"),
|
||||
"/conf/homeserver.d/oidc_provider.yaml",
|
||||
[]byte(OIDC_HOMESERVER_CONFIG),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write updated config to container: %v", err)
|
||||
}
|
||||
|
||||
// Restart the homeserver to apply the new config
|
||||
deployment.StopServer(t, "hs1")
|
||||
// Careful: port number changes here
|
||||
deployment.StartServer(t, "hs1")
|
||||
// Must get after the restart so the port number is correct
|
||||
unauthedClient := deployment.UnauthenticatedClient(t, "hs1")
|
||||
|
||||
// Test that trying to log in with an OIDC provider that is down
|
||||
// causes an HTML error page to be shown to the user.
|
||||
// (This replaces the redirect that would happen if the provider was
|
||||
// up.)
|
||||
//
|
||||
// More importantly, implicitly tests that Synapse can start up
|
||||
// and answer requests even though an OIDC provider is down.
|
||||
t.Run("/login/sso/redirect shows HTML error", func(t *testing.T) {
|
||||
// Build a request to the /redirect/ endpoint, that would normally be navigated to
|
||||
// by the user's browser in order to start the login flow.
|
||||
queryParams := url.Values{}
|
||||
queryParams.Add("redirectUrl", "http://redirect.invalid/redirect")
|
||||
res := unauthedClient.Do(
|
||||
t,
|
||||
"GET",
|
||||
[]string{"_matrix", "client", "v3", "login", "sso", "redirect", "oidc-test_provider"},
|
||||
client.WithQueries(queryParams),
|
||||
)
|
||||
|
||||
body := must.MatchResponse(t, res, match.HTTPResponse{
|
||||
// Should get a 503
|
||||
StatusCode: http.StatusServiceUnavailable,
|
||||
|
||||
Headers: map[string]string{
|
||||
// Should get an HTML page explaining the problem to the user
|
||||
"Content-Type": "text/html; charset=utf-8",
|
||||
},
|
||||
})
|
||||
|
||||
bodyText := string(body)
|
||||
|
||||
// The HTML page contains phrases from the template we expect
|
||||
if !strings.Contains(bodyText, "login provider is unavailable right now") {
|
||||
t.Fatalf("Keyword not found in HTML error page, got %s", bodyText)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
// This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
//
|
||||
// Copyright (C) 2026 Element Creations Ltd
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// See the GNU Affero General Public License for more details:
|
||||
// <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
|
||||
package synapse_tests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/complement"
|
||||
"github.com/matrix-org/complement/b"
|
||||
"github.com/matrix-org/complement/client"
|
||||
"github.com/matrix-org/complement/helpers"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func TestMessagesOverFederation(t *testing.T) {
|
||||
deployment := complement.Deploy(t, 2)
|
||||
defer deployment.Destroy(t)
|
||||
|
||||
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{
|
||||
LocalpartSuffix: "alice",
|
||||
})
|
||||
bob := deployment.Register(t, "hs2", helpers.RegistrationOpts{
|
||||
LocalpartSuffix: "bob",
|
||||
})
|
||||
|
||||
// The typical convention to find backfill points is from the backward extremities in
|
||||
// the DAG. Backward extremities are the oldest events we know of in the room but we
|
||||
// only know of them because some other event referenced them by prev_event and aren't
|
||||
// known to the homeserver yet (meaning we don't know their depth specifically). So we
|
||||
// can only do approximate depth comparisons (use the depth of the known events
|
||||
// they're connected to). And we don't know if those backward extremities point to a
|
||||
// long chain/fork of history that could stretch back far enough to be visible.
|
||||
//
|
||||
// This means a naive homeserver implementation that looks for backward extremities <=
|
||||
// depth of the `/messages?dir=b&from=xxx` token may overlook a backfill point that could
|
||||
// reveal more history in the window the user is currently paginating in.
|
||||
//
|
||||
// This could be a near miss as this test is specifically stressing or a more deep miss
|
||||
// as the backward extremity could reveal an entire fork of history that stretches
|
||||
// back far enough to be visible.
|
||||
//
|
||||
// In Synapse, we consider "nearby" as anything within range of the `limit` specified
|
||||
// in `/messages?dir=b&from=xxx&limit=xxx`.
|
||||
//
|
||||
// This test lives in our in-repo Complement tests for Synapse because the Matrix spec
|
||||
// doesn't have any rules for how a homeserver should backfill. Practically speaking,
|
||||
// homeservers that don't do anything for this problem will just hide messages from
|
||||
// clients. This underscores the fact why it's necessary for homeservers to indicate that
|
||||
// there is a gap (using MSC3871) at the very least.
|
||||
//
|
||||
// --------------------------------------------------
|
||||
//
|
||||
// Even with MSC3871 gaps, the tested behavior here is necessary as the gap prev/next
|
||||
// tokens point before/after the event (remember: tokens are positions between
|
||||
// events), so if you use `/messages?dir=b&from=<gap prev_pagination_token>`, we can't
|
||||
// rely on naive depth comparison. MSC3871 Complement tests will also exercise this.
|
||||
// Example:
|
||||
//
|
||||
// t0 t1 t2 t3 t4
|
||||
// [A] <--- [B] <--- [C] <--- [bob join 4]
|
||||
//
|
||||
// When Bob calls `/messages?dir=b&backfill=false`, he sees a gap (`{ event_id: "bob
|
||||
// join 4", prev_pagination_token: "t3", next_pagination_token: "t4" }`) and tries to
|
||||
// fill it in with `/messages?dir=b&from=t3&limit=10&backfill=true`. To find backfill
|
||||
// points, Synapse will compare `t3` with the backward extremity at an approximate
|
||||
// depth of 4. Which is why we take `t3`, add the `limit=10` and then do the
|
||||
// comparison (find any backfill points with an approximate depth <= 13).
|
||||
t.Run("Backfill from nearby backward extremities past token", func(t *testing.T) {
|
||||
// Alice creates the room
|
||||
roomID := alice.MustCreateRoom(t, map[string]interface{}{
|
||||
// The `public_chat` preset includes `history_visibility: "shared"` ("Previous
|
||||
// events are always accessible to newly joined members. All events in the
|
||||
// room are accessible, even those sent when the member was not a part of the
|
||||
// room."), which is what we want to test.
|
||||
"preset": "public_chat",
|
||||
})
|
||||
|
||||
// Keep track of the order
|
||||
eventIDs := make([]string, 0)
|
||||
// Map from event_id to event info
|
||||
eventMap := make(map[string]EventInfo)
|
||||
|
||||
// Send some message history into the room
|
||||
numberOfMessagesToSend := 3
|
||||
messageDrafts := make([]MessageDraft, 0, numberOfMessagesToSend)
|
||||
for i := 0; i < numberOfMessagesToSend; i++ {
|
||||
messageDrafts = append(
|
||||
messageDrafts,
|
||||
MessageDraft{alice, fmt.Sprintf("message history %d", i+1)},
|
||||
)
|
||||
}
|
||||
sendAndTrackMessages(t, roomID, messageDrafts, &eventIDs, &eventMap)
|
||||
|
||||
// Bob joins the room
|
||||
bob.MustJoinRoom(t, roomID, []spec.ServerName{
|
||||
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
|
||||
})
|
||||
bobJoinEventID := getStateID(t, bob, roomID, "m.room.member", bob.UserID)
|
||||
|
||||
// Make it easy to cross-reference the events being talked about in the logs
|
||||
for eventIndex, eventID := range eventIDs {
|
||||
t.Logf("Message %d -> event_id=%s", eventIndex, eventID)
|
||||
}
|
||||
|
||||
// Use a `/context` request to get a pagination token just before Bob's join event
|
||||
// (remember: tokens are positions between events)
|
||||
//
|
||||
// Usually a client would just use `/messages?dir=b` to start getting history
|
||||
// after joining but this is valid as well. To illustrate a more real example of
|
||||
// this, someone can use `/timestamp_to_event` to jump back in history and
|
||||
// `/context` to start paginating history.
|
||||
contextRes := bob.MustDo(
|
||||
t,
|
||||
"GET",
|
||||
[]string{"_matrix", "client", "v3", "rooms", roomID, "context", bobJoinEventID},
|
||||
client.WithContentType("application/json"),
|
||||
client.WithQueries(url.Values{
|
||||
"limit": []string{"0"},
|
||||
}),
|
||||
)
|
||||
contextResResBody := client.ParseJSON(t, contextRes)
|
||||
// > `start`: A token that can be used to paginate backwards with.
|
||||
// > - https://spec.matrix.org/v1.17/client-server-api/#get_matrixclientv3roomsroomidcontexteventid
|
||||
paginationToken := client.GetJSONFieldStr(t, contextResResBody, "start")
|
||||
|
||||
// Paginate backwards from the join event
|
||||
messagesRes := bob.MustDo(
|
||||
t,
|
||||
"GET",
|
||||
[]string{"_matrix", "client", "v3", "rooms", roomID, "messages"},
|
||||
client.WithContentType("application/json"),
|
||||
client.WithQueries(url.Values{
|
||||
"dir": []string{"b"},
|
||||
"limit": []string{"100"},
|
||||
"from": []string{paginationToken},
|
||||
}),
|
||||
)
|
||||
messagesResBody := client.ParseJSON(t, messagesRes)
|
||||
|
||||
// Since `dir=b`, these will be in reverse chronological order
|
||||
actualEventIDsFromRequest := extractEventIDsFromMessagesResponse(t, messagesResBody)
|
||||
|
||||
// Put them in chronological order to match the expected list
|
||||
chronologicalActualEventIds := slices.Clone(actualEventIDsFromRequest)
|
||||
slices.Reverse(chronologicalActualEventIds)
|
||||
|
||||
// Assert timeline order
|
||||
assertEventsInOrder(t, chronologicalActualEventIds, eventIDs)
|
||||
})
|
||||
|
||||
// TODO: Backfill test to make sure we backfill from forks when viewing history (see
|
||||
// docstring above).
|
||||
//
|
||||
// 1. Alice (hs1, engineered homeserver) creates a room with events A, B
|
||||
// 1. Bob (hs2) joins the room
|
||||
// 1. Bob leaves the room
|
||||
// 1. Alice creates a fork from A with some history (1, 2, 3) and connects it back with a new event C
|
||||
// 1. Bob joins back
|
||||
// 1. Bob paginates `/messages?dir=b&from=<token-after-b>`
|
||||
// 1. Ensure Bob sees events: B, 2, 1, A
|
||||
//
|
||||
// 1 <--- 2 <----- 3
|
||||
// / \
|
||||
// A <------- B ▲ <--- C <-- D
|
||||
// |
|
||||
// Paginate backwards from this point
|
||||
// t.Run("Backfill from nearby backward extremities past token (fork)", func(t *testing.T) {
|
||||
}
|
||||
|
||||
// These utilities match what we're using in the Complement repo (see
|
||||
// `matrix-org/complement` -> `tests/csapi/room_messages_test.go`)
|
||||
|
||||
type MessageDraft struct {
|
||||
Sender *client.CSAPI
|
||||
Message string
|
||||
}
|
||||
|
||||
type EventInfo struct {
|
||||
MessageDraft MessageDraft
|
||||
EventID string
|
||||
}
|
||||
|
||||
func sendMessageDrafts(
|
||||
t *testing.T,
|
||||
roomID string,
|
||||
messageDrafts []MessageDraft,
|
||||
) []string {
|
||||
t.Helper()
|
||||
|
||||
eventIDs := make([]string, len(messageDrafts))
|
||||
for messageDraftIndex, messageDraft := range messageDrafts {
|
||||
eventID := messageDraft.Sender.SendEventSynced(t, roomID, b.Event{
|
||||
Type: "m.room.message",
|
||||
Content: map[string]interface{}{
|
||||
"msgtype": "m.text",
|
||||
"body": messageDraft.Message,
|
||||
},
|
||||
})
|
||||
eventIDs[messageDraftIndex] = eventID
|
||||
}
|
||||
|
||||
return eventIDs
|
||||
}
|
||||
|
||||
// sendAndTrackMessages sends the given message drafts to the room, keeping track of the
|
||||
// new events in the list of `eventIDs` and `eventMap`. Returns the list of new event
|
||||
// IDs that were sent.
|
||||
func sendAndTrackMessages(
|
||||
t *testing.T,
|
||||
roomID string,
|
||||
messageDrafts []MessageDraft,
|
||||
eventIDs *[]string,
|
||||
eventMap *map[string]EventInfo,
|
||||
) []string {
|
||||
t.Helper()
|
||||
|
||||
newEventIDs := sendMessageDrafts(t, roomID, messageDrafts)
|
||||
|
||||
*eventIDs = append(*eventIDs, newEventIDs...)
|
||||
for i, eventID := range newEventIDs {
|
||||
(*eventMap)[eventID] = EventInfo{
|
||||
MessageDraft: messageDrafts[i],
|
||||
EventID: eventID,
|
||||
}
|
||||
}
|
||||
|
||||
return newEventIDs
|
||||
}
|
||||
|
||||
// extractEventIDsFromMessagesResponse extracts the event IDs from the given
|
||||
// `/messages` response body.
|
||||
func extractEventIDsFromMessagesResponse(
|
||||
t *testing.T,
|
||||
messagesResBody json.RawMessage,
|
||||
) []string {
|
||||
t.Helper()
|
||||
|
||||
wantKey := "chunk"
|
||||
keyRes := gjson.GetBytes(messagesResBody, wantKey)
|
||||
if !keyRes.Exists() {
|
||||
t.Fatalf("extractEventIDsFromMessagesResponse: missing key '%s'", wantKey)
|
||||
}
|
||||
if !keyRes.IsArray() {
|
||||
t.Fatalf(
|
||||
"extractEventIDsFromMessagesResponse: key '%s' is not an array (was %s)",
|
||||
wantKey,
|
||||
keyRes.Type,
|
||||
)
|
||||
}
|
||||
|
||||
var eventIDs []string
|
||||
actualEvents := keyRes.Array()
|
||||
for _, event := range actualEvents {
|
||||
eventIDs = append(eventIDs, event.Get("event_id").Str)
|
||||
}
|
||||
|
||||
return eventIDs
|
||||
}
|
||||
|
||||
func filterEventIDs(t *testing.T, actualEventIDs []string, expectedEventIDs []string) []string {
|
||||
t.Helper()
|
||||
|
||||
relevantActualEventIDs := make([]string, 0, len(expectedEventIDs))
|
||||
for _, eventID := range actualEventIDs {
|
||||
if slices.Contains(expectedEventIDs, eventID) {
|
||||
relevantActualEventIDs = append(relevantActualEventIDs, eventID)
|
||||
}
|
||||
}
|
||||
|
||||
return relevantActualEventIDs
|
||||
}
|
||||
|
||||
// assertEventsInOrder asserts all `actualEventIDs` are present and in order according
|
||||
// to `expectedEventIDs`. Other unrelated events can be in between.
|
||||
func assertEventsInOrder(t *testing.T, actualEventIDs []string, expectedEventIDs []string) {
|
||||
t.Helper()
|
||||
|
||||
relevantActualEventIDs := filterEventIDs(t, actualEventIDs, expectedEventIDs)
|
||||
|
||||
if len(relevantActualEventIDs) != len(expectedEventIDs) {
|
||||
t.Fatalf(
|
||||
"expected %d events in timeline (got %d relevant events filtered down from %d events)\n%s",
|
||||
len(expectedEventIDs),
|
||||
len(relevantActualEventIDs),
|
||||
len(actualEventIDs),
|
||||
generateEventOrderDiffString(relevantActualEventIDs, expectedEventIDs),
|
||||
)
|
||||
}
|
||||
|
||||
for i, eventID := range relevantActualEventIDs {
|
||||
if eventID != expectedEventIDs[i] {
|
||||
t.Fatalf(
|
||||
"expected event ID %s (got %s) at index %d\n%s",
|
||||
expectedEventIDs[i],
|
||||
eventID,
|
||||
i,
|
||||
generateEventOrderDiffString(relevantActualEventIDs, expectedEventIDs),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateEventOrderDiffString(actualEventIDs []string, expectedEventIDs []string) string {
|
||||
expectedLines := make([]string, len(expectedEventIDs))
|
||||
for i, expectedEventID := range expectedEventIDs {
|
||||
isExpectedInActual := slices.Contains(actualEventIDs, expectedEventID)
|
||||
isMissingIndicatorString := " "
|
||||
if !isExpectedInActual {
|
||||
isMissingIndicatorString = "?"
|
||||
}
|
||||
|
||||
expectedLines[i] = fmt.Sprintf("%2d: %s %s", i, isMissingIndicatorString, expectedEventID)
|
||||
}
|
||||
expectedDiffString := strings.Join(expectedLines, "\n")
|
||||
|
||||
actualLines := make([]string, len(actualEventIDs))
|
||||
for actualEventIndex, actualEventID := range actualEventIDs {
|
||||
isActualInExpected := slices.Contains(expectedEventIDs, actualEventID)
|
||||
isActualInExpectedIndicatorString := " "
|
||||
if isActualInExpected {
|
||||
isActualInExpectedIndicatorString = "+"
|
||||
}
|
||||
|
||||
expectedIndex := slices.Index(expectedEventIDs, actualEventID)
|
||||
expectedIndexString := ""
|
||||
if actualEventIndex != expectedIndex {
|
||||
expectedDirectionString := "⬆️"
|
||||
if expectedIndex > actualEventIndex {
|
||||
expectedDirectionString = "⬇️"
|
||||
}
|
||||
|
||||
expectedIndexString = fmt.Sprintf(
|
||||
" (expected index %d %s)",
|
||||
expectedIndex,
|
||||
expectedDirectionString,
|
||||
)
|
||||
}
|
||||
|
||||
actualLines[actualEventIndex] = fmt.Sprintf("%2d: %s %s%s",
|
||||
actualEventIndex, isActualInExpectedIndicatorString, actualEventID, expectedIndexString,
|
||||
)
|
||||
}
|
||||
actualDiffString := strings.Join(actualLines, "\n")
|
||||
|
||||
return fmt.Sprintf(
|
||||
"Actual events ('+' = found expected items):\n%s\nExpected events ('?' = missing expected items):\n%s",
|
||||
actualDiffString,
|
||||
expectedDiffString,
|
||||
)
|
||||
}
|
||||
|
||||
func getStateID(
|
||||
t *testing.T,
|
||||
c *client.CSAPI,
|
||||
roomID string,
|
||||
stateType string,
|
||||
stateKey string,
|
||||
) string {
|
||||
t.Helper()
|
||||
|
||||
stateRes := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state"})
|
||||
stateResBody := client.ParseJSON(t, stateRes)
|
||||
eventJSON := gjson.ParseBytes(stateResBody)
|
||||
if !eventJSON.IsArray() {
|
||||
t.Fatalf("expected array of state events but found %s", eventJSON.Type)
|
||||
}
|
||||
|
||||
events := eventJSON.Array()
|
||||
|
||||
for _, event := range events {
|
||||
if event.Get("type").Str == stateType && event.Get("state_key").Str == stateKey {
|
||||
return event.Get("event_id").Str
|
||||
}
|
||||
}
|
||||
|
||||
t.Fatalf("Unable to find state event for (%s, %s). Room state: %s", stateType, stateKey, events)
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
//
|
||||
// Copyright (C) 2026 Element Creations Ltd
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// See the GNU Affero General Public License for more details:
|
||||
// <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
|
||||
package synapse_tests
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/complement"
|
||||
"github.com/matrix-org/complement/match"
|
||||
"github.com/matrix-org/complement/must"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func TestSynapseVersion(t *testing.T) {
|
||||
deployment := complement.Deploy(t, 1)
|
||||
defer deployment.Destroy(t)
|
||||
|
||||
unauthedClient := deployment.UnauthenticatedClient(t, "hs1")
|
||||
|
||||
// Sanity check that the version of Synapse used in the `COMPLEMENT_BASE_IMAGE`
|
||||
// matches the same git commit we have checked out. This ensures that the image being
|
||||
// used in Complement is the one that we just built locally with `complement.sh`
|
||||
// instead of accidentally pulling in some remote one.
|
||||
//
|
||||
// This test is expected to pass if you use `complement.sh`.
|
||||
//
|
||||
// If this test fails, it probably means that Complement is using an image that
|
||||
// doesn't encompass the changes you have checked out (unexpected). We want to yell
|
||||
// loudly and point out what's wrong instead of silently letting your PRs pass
|
||||
// without actually being tested.
|
||||
t.Run("Synapse version matches current git checkout", func(t *testing.T) {
|
||||
// Get the Synapse version details of the current git checkout
|
||||
checkoutSynapseVersion := runCommand(
|
||||
t,
|
||||
[]string{
|
||||
"poetry",
|
||||
"run",
|
||||
"python",
|
||||
"-c",
|
||||
"from synapse.util import SYNAPSE_VERSION; print(SYNAPSE_VERSION)",
|
||||
},
|
||||
)
|
||||
|
||||
// Find the version details of the Synapse instance deployed from the Docker image
|
||||
res := unauthedClient.MustDo(t, "GET", []string{"_matrix", "federation", "v1", "version"})
|
||||
body := must.MatchResponse(t, res, match.HTTPResponse{
|
||||
StatusCode: http.StatusOK,
|
||||
JSON: []match.JSON{
|
||||
match.JSONKeyPresent("server"),
|
||||
},
|
||||
})
|
||||
rawSynapseVersionString := gjson.GetBytes(body, "server.version").Str
|
||||
t.Logf(
|
||||
"Synapse version string from federation version endpoint: %s",
|
||||
rawSynapseVersionString,
|
||||
)
|
||||
|
||||
must.Equal(
|
||||
t,
|
||||
rawSynapseVersionString,
|
||||
checkoutSynapseVersion,
|
||||
"Synapse version in the checkout doesn't match the Synapse version that Complement is running. "+
|
||||
"If this test fails, it probably means that Complement is using an image that "+
|
||||
"doesn't encompass the changes you have checked out (unexpected). We want to yell "+
|
||||
"loudly and point out what's wrong instead of silently letting your PRs pass "+
|
||||
"without actually being tested.",
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// runCommand will run the given command and return the stdout (whitespace
|
||||
// trimmed).
|
||||
func runCommand(t *testing.T, commandPieces []string) string {
|
||||
t.Helper()
|
||||
|
||||
// Then run our actual command
|
||||
cmd := exec.Command(commandPieces[0], commandPieces[1:]...)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
"runCommand: failed to run command (%s): %v",
|
||||
strings.Join(commandPieces, " "),
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(output))
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import sys
|
||||
import time
|
||||
import urllib
|
||||
from http import TwistedHttpClient
|
||||
from typing import Optional
|
||||
|
||||
import urlparse
|
||||
from signedjson.key import NACL_ED25519, decode_verify_key_bytes
|
||||
@@ -726,7 +725,7 @@ class SynapseCmd(cmd.Cmd):
|
||||
method,
|
||||
path,
|
||||
data=None,
|
||||
query_params: Optional[dict] = None,
|
||||
query_params: dict | None = None,
|
||||
alt_text=None,
|
||||
):
|
||||
"""Runs an HTTP request and pretty prints the output.
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
import json
|
||||
import urllib
|
||||
from pprint import pformat
|
||||
from typing import Optional
|
||||
|
||||
from twisted.internet import defer, reactor
|
||||
from twisted.web.client import Agent, readBody
|
||||
@@ -90,7 +89,7 @@ class TwistedHttpClient(HttpClient):
|
||||
body = yield readBody(response)
|
||||
return json.loads(body)
|
||||
|
||||
def _create_put_request(self, url, json_data, headers_dict: Optional[dict] = None):
|
||||
def _create_put_request(self, url, json_data, headers_dict: dict | None = None):
|
||||
"""Wrapper of _create_request to issue a PUT request"""
|
||||
headers_dict = headers_dict or {}
|
||||
|
||||
@@ -101,7 +100,7 @@ class TwistedHttpClient(HttpClient):
|
||||
"PUT", url, producer=_JsonProducer(json_data), headers_dict=headers_dict
|
||||
)
|
||||
|
||||
def _create_get_request(self, url, headers_dict: Optional[dict] = None):
|
||||
def _create_get_request(self, url, headers_dict: dict | None = None):
|
||||
"""Wrapper of _create_request to issue a GET request"""
|
||||
return self._create_request("GET", url, headers_dict=headers_dict or {})
|
||||
|
||||
@@ -113,7 +112,7 @@ class TwistedHttpClient(HttpClient):
|
||||
data=None,
|
||||
qparams=None,
|
||||
jsonreq=True,
|
||||
headers: Optional[dict] = None,
|
||||
headers: dict | None = None,
|
||||
):
|
||||
headers = headers or {}
|
||||
|
||||
@@ -138,7 +137,7 @@ class TwistedHttpClient(HttpClient):
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _create_request(
|
||||
self, method, url, producer=None, headers_dict: Optional[dict] = None
|
||||
self, method, url, producer=None, headers_dict: dict | None = None
|
||||
):
|
||||
"""Creates and sends a request to the given url"""
|
||||
headers_dict = headers_dict or {}
|
||||
|
||||
+1038
-6682
File diff suppressed because it is too large.
Load diff
@@ -24,7 +24,6 @@ import datetime
|
||||
import html
|
||||
import json
|
||||
import urllib.request
|
||||
from typing import List
|
||||
|
||||
import pydot
|
||||
|
||||
@@ -33,7 +32,7 @@ def make_name(pdu_id: str, origin: str) -> str:
|
||||
return f"{pdu_id}@{origin}"
|
||||
|
||||
|
||||
def make_graph(pdus: List[dict], filename_prefix: str) -> None:
|
||||
def make_graph(pdus: list[dict], filename_prefix: str) -> None:
|
||||
"""
|
||||
Generate a dot and SVG file for a graph of events in the room based on the
|
||||
topological ordering by querying a homeserver.
|
||||
@@ -127,7 +126,7 @@ def make_graph(pdus: List[dict], filename_prefix: str) -> None:
|
||||
graph.write_svg("%s.svg" % filename_prefix, prog="dot")
|
||||
|
||||
|
||||
def get_pdus(host: str, room: str) -> List[dict]:
|
||||
def get_pdus(host: str, room: str) -> list[dict]:
|
||||
transaction = json.loads(
|
||||
urllib.request.urlopen(
|
||||
f"http://{host}/_matrix/federation/v1/context/{room}/"
|
||||
|
||||
@@ -44,31 +44,3 @@ groups:
|
||||
###
|
||||
### End of 'Prometheus Console Only' rules block
|
||||
###
|
||||
|
||||
|
||||
###
|
||||
### Grafana Only
|
||||
### The following rules are only needed if you use the Grafana dashboard
|
||||
### in contrib/grafana/synapse.json
|
||||
###
|
||||
- record: synapse_storage_events_persisted_by_source_type
|
||||
expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep_total{origin_type="remote"})
|
||||
labels:
|
||||
type: remote
|
||||
- record: synapse_storage_events_persisted_by_source_type
|
||||
expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep_total{origin_entity="*client*",origin_type="local"})
|
||||
labels:
|
||||
type: local
|
||||
- record: synapse_storage_events_persisted_by_source_type
|
||||
expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep_total{origin_entity!="*client*",origin_type="local"})
|
||||
labels:
|
||||
type: bridges
|
||||
|
||||
- record: synapse_storage_events_persisted_by_event_type
|
||||
expr: sum without(origin_entity, origin_type) (synapse_storage_events_persisted_events_sep_total)
|
||||
|
||||
- record: synapse_storage_events_persisted_by_origin
|
||||
expr: sum without(type) (synapse_storage_events_persisted_events_sep_total)
|
||||
###
|
||||
### End of 'Grafana Only' rules block
|
||||
###
|
||||
@@ -16,3 +16,9 @@ appropriate locations of your installation.
|
||||
5. Start Synapse: `sudo systemctl start matrix-synapse`
|
||||
6. Verify Synapse is running: `sudo systemctl status matrix-synapse`
|
||||
7. *optional* Enable Synapse to start at system boot: `sudo systemctl enable matrix-synapse`
|
||||
|
||||
## Logging
|
||||
|
||||
If you use `contrib/systemd/log_config.yaml`, install `systemd-python` in the
|
||||
same Python environment as Synapse. The config uses
|
||||
`systemd.journal.JournalHandler`, which requires that package.
|
||||
@@ -1,5 +1,6 @@
|
||||
version: 1
|
||||
|
||||
# Requires the `systemd-python` package in Synapse's runtime environment.
|
||||
# In systemd's journal, loglevel is implicitly stored, so let's omit it
|
||||
# from the message text.
|
||||
formatters:
|
||||
|
||||
Vendored
+5
-3
@@ -35,12 +35,14 @@ TEMP_VENV="$(mktemp -d)"
|
||||
python3 -m venv "$TEMP_VENV"
|
||||
source "$TEMP_VENV/bin/activate"
|
||||
pip install -U pip
|
||||
pip install poetry==2.1.1 poetry-plugin-export==1.9.0
|
||||
pip install poetry==2.4.1 poetry-plugin-export==1.9.0
|
||||
poetry export \
|
||||
--extras all \
|
||||
--extras test \
|
||||
--extras systemd \
|
||||
-o exported_requirements.txt
|
||||
# Keep journald logging support in the packaged virtualenv when using
|
||||
# systemd.journal.JournalHandler in /etc/matrix-synapse/log.yaml.
|
||||
echo "systemd-python==235 --hash=sha256:4e57f39797fd5d9e2d22b8806a252d7c0106c936039d1e71c8c6b8008e695c0a" >> exported_requirements.txt
|
||||
deactivate
|
||||
rm -rf "$TEMP_VENV"
|
||||
|
||||
@@ -57,7 +59,7 @@ dh_virtualenv \
|
||||
--extra-pip-arg="--no-deps" \
|
||||
--extra-pip-arg="--no-cache-dir" \
|
||||
--extra-pip-arg="--compile" \
|
||||
--extras="all,systemd,test" \
|
||||
--extras="all,test" \
|
||||
--requirements="exported_requirements.txt"
|
||||
|
||||
PACKAGE_BUILD_DIR="$(pwd)/debian/matrix-synapse-py3"
|
||||
|
||||
Vendored
+312
@@ -1,3 +1,315 @@
|
||||
matrix-synapse-py3 (1.157.2) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.157.2.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 28 Jul 2026 14:01:25 +0100
|
||||
|
||||
matrix-synapse-py3 (1.157.1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.157.1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 22 Jul 2026 14:30:55 +0000
|
||||
|
||||
matrix-synapse-py3 (1.157.0) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.157.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 21 Jul 2026 15:17:02 +0000
|
||||
|
||||
matrix-synapse-py3 (1.157.0~rc1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.157.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 14 Jul 2026 21:18:16 +0000
|
||||
|
||||
matrix-synapse-py3 (1.156.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.156.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 07 Jul 2026 14:20:22 +0100
|
||||
|
||||
matrix-synapse-py3 (1.156.0~rc1) stable; urgency=medium
|
||||
|
||||
* Bump poetry from 2.2.1 to 2.4.1.
|
||||
* New Synapse release 1.156.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 30 Jun 2026 14:37:46 +0100
|
||||
|
||||
matrix-synapse-py3 (1.155.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.155.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 16 Jun 2026 14:44:04 +0100
|
||||
|
||||
matrix-synapse-py3 (1.155.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.155.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 09 Jun 2026 14:58:03 +0100
|
||||
|
||||
matrix-synapse-py3 (1.154.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.154.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Thu, 04 Jun 2026 14:16:23 +0100
|
||||
|
||||
matrix-synapse-py3 (1.154.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.154.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 27 May 2026 12:23:54 +0100
|
||||
|
||||
matrix-synapse-py3 (1.153.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.153.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 19 May 2026 14:12:51 +0100
|
||||
|
||||
matrix-synapse-py3 (1.153.0~rc3) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.153.0rc3.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Fri, 15 May 2026 11:42:29 +0100
|
||||
|
||||
matrix-synapse-py3 (1.153.0~rc2) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.153.0rc2.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 13 May 2026 12:00:39 +0100
|
||||
|
||||
matrix-synapse-py3 (1.153.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.153.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Fri, 08 May 2026 13:05:08 +0100
|
||||
|
||||
matrix-synapse-py3 (1.152.1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.152.1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Thu, 07 May 2026 13:29:05 +0100
|
||||
|
||||
matrix-synapse-py3 (1.152.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.152.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 28 Apr 2026 11:45:01 +0100
|
||||
|
||||
matrix-synapse-py3 (1.152.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.152.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 22 Apr 2026 12:03:58 +0100
|
||||
|
||||
matrix-synapse-py3 (1.151.0) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.151.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 07 Apr 2026 12:15:10 +0000
|
||||
|
||||
matrix-synapse-py3 (1.151.0~rc1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.151.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 31 Mar 2026 12:23:34 +0000
|
||||
|
||||
matrix-synapse-py3 (1.150.0) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.150.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 24 Mar 2026 14:17:04 +0000
|
||||
|
||||
matrix-synapse-py3 (1.150.0~rc1) stable; urgency=medium
|
||||
|
||||
[ Quentin Gliech ]
|
||||
* Change how the systemd journald integration is installed.
|
||||
* Update Poetry used at build time to 2.2.1.
|
||||
|
||||
[ Synapse Packaging team ]
|
||||
* New synapse release 1.150.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 17 Mar 2026 14:56:35 +0000
|
||||
|
||||
matrix-synapse-py3 (1.149.1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.149.1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 11 Mar 2026 09:30:24 +0000
|
||||
|
||||
matrix-synapse-py3 (1.149.0) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.149.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 10 Mar 2026 13:02:53 +0000
|
||||
|
||||
matrix-synapse-py3 (1.149.0~rc1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.149.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 03 Mar 2026 14:37:57 +0000
|
||||
|
||||
matrix-synapse-py3 (1.148.0) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.148.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 24 Feb 2026 11:17:49 +0000
|
||||
|
||||
matrix-synapse-py3 (1.148.0~rc1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.148.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 17 Feb 2026 16:44:08 +0000
|
||||
|
||||
matrix-synapse-py3 (1.147.1) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.147.1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Thu, 12 Feb 2026 15:45:15 +0000
|
||||
|
||||
matrix-synapse-py3 (1.147.0) stable; urgency=medium
|
||||
|
||||
* New synapse release 1.147.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 10 Feb 2026 12:39:58 +0000
|
||||
|
||||
matrix-synapse-py3 (1.147.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.147.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 03 Feb 2026 08:53:17 -0700
|
||||
|
||||
matrix-synapse-py3 (1.146.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.146.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 27 Jan 2026 08:43:59 -0700
|
||||
|
||||
matrix-synapse-py3 (1.146.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.146.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 20 Jan 2026 08:42:10 -0700
|
||||
|
||||
matrix-synapse-py3 (1.145.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.145.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 13 Jan 2026 08:37:42 -0700
|
||||
|
||||
matrix-synapse-py3 (1.145.0~rc4) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.145.0rc4.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Thu, 08 Jan 2026 12:06:35 -0700
|
||||
|
||||
matrix-synapse-py3 (1.145.0~rc3) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.145.0rc3.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 07 Jan 2026 15:32:07 -0700
|
||||
|
||||
matrix-synapse-py3 (1.145.0~rc2) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.145.0rc2.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 07 Jan 2026 10:10:07 -0700
|
||||
|
||||
matrix-synapse-py3 (1.145.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.145.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 06 Jan 2026 09:29:39 -0700
|
||||
|
||||
matrix-synapse-py3 (1.144.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.144.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 09 Dec 2025 08:30:40 -0700
|
||||
|
||||
matrix-synapse-py3 (1.144.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.144.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 02 Dec 2025 09:11:19 -0700
|
||||
|
||||
matrix-synapse-py3 (1.143.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.143.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 25 Nov 2025 08:44:56 -0700
|
||||
|
||||
matrix-synapse-py3 (1.143.0~rc2) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.143.0rc2.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 18 Nov 2025 17:36:08 -0700
|
||||
|
||||
matrix-synapse-py3 (1.143.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.143.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 18 Nov 2025 13:08:39 -0700
|
||||
|
||||
matrix-synapse-py3 (1.142.1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.142.1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 18 Nov 2025 12:25:23 -0700
|
||||
|
||||
matrix-synapse-py3 (1.142.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.142.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 11 Nov 2025 09:45:51 +0000
|
||||
|
||||
matrix-synapse-py3 (1.142.0~rc4) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.142.0rc4.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Fri, 07 Nov 2025 10:54:42 +0000
|
||||
|
||||
matrix-synapse-py3 (1.142.0~rc3) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.142.0rc3.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 04 Nov 2025 17:39:11 +0000
|
||||
|
||||
matrix-synapse-py3 (1.142.0~rc2) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.142.0rc2.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 04 Nov 2025 16:21:30 +0000
|
||||
|
||||
matrix-synapse-py3 (1.142.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.142.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 04 Nov 2025 13:20:15 +0000
|
||||
|
||||
matrix-synapse-py3 (1.141.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.141.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 29 Oct 2025 11:01:43 +0000
|
||||
|
||||
matrix-synapse-py3 (1.141.0~rc2) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.141.0rc2.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 28 Oct 2025 10:20:26 +0000
|
||||
|
||||
matrix-synapse-py3 (1.141.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.141.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 21 Oct 2025 11:01:44 +0100
|
||||
|
||||
matrix-synapse-py3 (1.140.0) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.140.0.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 14 Oct 2025 15:22:36 +0100
|
||||
|
||||
matrix-synapse-py3 (1.140.0~rc1) stable; urgency=medium
|
||||
|
||||
* New Synapse release 1.140.0rc1.
|
||||
|
||||
+7
-1
@@ -49,7 +49,7 @@ for port in 8080 8081 8082; do
|
||||
# Please don't accidentally bork me with your fancy settings.
|
||||
listeners=$(cat <<-PORTLISTENERS
|
||||
# Configure server to listen on both $https_port and $port
|
||||
# This overides some of the default settings above
|
||||
# This overrides some of the default settings above
|
||||
listeners:
|
||||
- port: $https_port
|
||||
type: http
|
||||
@@ -145,6 +145,12 @@ for port in 8080 8081 8082; do
|
||||
rc_delayed_event_mgmt:
|
||||
per_second: 1000
|
||||
burst_count: 1000
|
||||
rc_room_creation:
|
||||
per_second: 1000
|
||||
burst_count: 1000
|
||||
rc_user_directory:
|
||||
per_second: 1000
|
||||
burst_count: 1000
|
||||
RC
|
||||
)
|
||||
echo "${ratelimiting}" >> "$port.config"
|
||||
|
||||
+24
-11
@@ -20,9 +20,9 @@
|
||||
# `poetry export | pip install -r /dev/stdin`, but beware: we have experienced bugs in
|
||||
# in `poetry export` in the past.
|
||||
|
||||
ARG DEBIAN_VERSION=bookworm
|
||||
ARG PYTHON_VERSION=3.12
|
||||
ARG POETRY_VERSION=2.1.1
|
||||
ARG DEBIAN_VERSION=trixie
|
||||
ARG PYTHON_VERSION=3.13
|
||||
ARG POETRY_VERSION=2.4.1
|
||||
|
||||
###
|
||||
### Stage 0: generate requirements.txt
|
||||
@@ -142,10 +142,10 @@ RUN \
|
||||
libwebp7 \
|
||||
xmlsec1 \
|
||||
libjemalloc2 \
|
||||
libicu \
|
||||
| grep '^\w' > /tmp/pkg-list && \
|
||||
for arch in arm64 amd64; do \
|
||||
mkdir -p /tmp/debs-${arch} && \
|
||||
chown _apt:root /tmp/debs-${arch} && \
|
||||
cd /tmp/debs-${arch} && \
|
||||
apt-get -o APT::Architecture="${arch}" download $(cat /tmp/pkg-list); \
|
||||
done
|
||||
@@ -171,24 +171,37 @@ FROM docker.io/library/python:${PYTHON_VERSION}-slim-${DEBIAN_VERSION}
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
# If specified, Synapse will use this as the version string in the app.
|
||||
#
|
||||
# This can be useful to capture the git info of the build as `.git/` won't be
|
||||
# available in the Docker image for Synapse to generate from.
|
||||
ARG SYNAPSE_VERSION_STRING
|
||||
# Pass it through to Synapse as an environment variable.
|
||||
ENV SYNAPSE_VERSION_STRING=${SYNAPSE_VERSION_STRING}
|
||||
|
||||
LABEL org.opencontainers.image.url='https://github.com/element-hq/synapse'
|
||||
LABEL org.opencontainers.image.documentation='https://element-hq.github.io/synapse/latest/'
|
||||
LABEL org.opencontainers.image.source='https://github.com/element-hq/synapse.git'
|
||||
LABEL org.opencontainers.image.licenses='AGPL-3.0-or-later OR LicenseRef-Element-Commercial'
|
||||
|
||||
# On the runtime image, /lib is a symlink to /usr/lib, so we need to copy the
|
||||
# libraries to the right place, else the `COPY` won't work.
|
||||
# On amd64, we'll also have a /lib64 folder with ld-linux-x86-64.so.2, which is
|
||||
# already present in the runtime image.
|
||||
COPY --from=runtime-deps /install-${TARGETARCH}/lib /usr/lib
|
||||
COPY --from=runtime-deps /install-${TARGETARCH}/etc /etc
|
||||
COPY --from=runtime-deps /install-${TARGETARCH}/usr /usr
|
||||
COPY --from=runtime-deps /install-${TARGETARCH}/var /var
|
||||
COPY --from=builder /install /usr/local
|
||||
|
||||
# Copy the installed python packages from the builder stage.
|
||||
#
|
||||
# uv will generate a `.lock` file when installing packages, which we don't want
|
||||
# to copy to the final image.
|
||||
COPY --from=builder --exclude=.lock /install /usr/local
|
||||
COPY ./docker/start.py /start.py
|
||||
COPY ./docker/conf /conf
|
||||
|
||||
EXPOSE 8008/tcp 8009/tcp 8448/tcp
|
||||
# 8008: CS Matrix API port from Synapse
|
||||
# 8448: SS Matrix API port from Synapse
|
||||
EXPOSE 8008/tcp 8448/tcp
|
||||
# 19090: Metrics listener port for the main process (metrics must be enabled with
|
||||
# SYNAPSE_ENABLE_METRICS=1).
|
||||
EXPOSE 19090/tcp
|
||||
|
||||
ENTRYPOINT ["/start.py"]
|
||||
|
||||
|
||||
+28
-13
@@ -1,9 +1,10 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
# syntax=docker/dockerfile:1-labs
|
||||
|
||||
ARG SYNAPSE_VERSION=latest
|
||||
ARG FROM=matrixdotorg/synapse:$SYNAPSE_VERSION
|
||||
ARG DEBIAN_VERSION=bookworm
|
||||
ARG PYTHON_VERSION=3.12
|
||||
ARG DEBIAN_VERSION=trixie
|
||||
ARG PYTHON_VERSION=3.13
|
||||
ARG REDIS_VERSION=7.2
|
||||
|
||||
# first of all, we create a base image with dependencies which we can copy into the
|
||||
# target image. For repeated rebuilds, this is much faster than apt installing
|
||||
@@ -11,15 +12,27 @@ ARG PYTHON_VERSION=3.12
|
||||
|
||||
FROM ghcr.io/astral-sh/uv:python${PYTHON_VERSION}-${DEBIAN_VERSION} AS deps_base
|
||||
|
||||
ARG DEBIAN_VERSION
|
||||
ARG REDIS_VERSION
|
||||
|
||||
# Tell apt to keep downloaded package files, as we're using cache mounts.
|
||||
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||
|
||||
# The upstream redis-server deb has fewer dynamic libraries than Debian's package which makes it easier to copy later on
|
||||
RUN \
|
||||
curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg && \
|
||||
chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg && \
|
||||
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb ${DEBIAN_VERSION} main" | tee /etc/apt/sources.list.d/redis.list
|
||||
|
||||
RUN \
|
||||
--mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update -qq && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends \
|
||||
nginx-light
|
||||
nginx-light \
|
||||
redis-server="6:${REDIS_VERSION}.*" redis-tools="6:${REDIS_VERSION}.*" \
|
||||
# libicu is required by postgres, see `docker/complement/Dockerfile`
|
||||
libicu76
|
||||
|
||||
RUN \
|
||||
# remove default page
|
||||
@@ -35,19 +48,12 @@ FROM ghcr.io/astral-sh/uv:python${PYTHON_VERSION}-${DEBIAN_VERSION} AS deps_base
|
||||
|
||||
RUN mkdir -p /uv/etc/supervisor/conf.d
|
||||
|
||||
# Similarly, a base to copy the redis server from.
|
||||
#
|
||||
# The redis docker image has fewer dynamic libraries than the debian package,
|
||||
# which makes it much easier to copy (but we need to make sure we use an image
|
||||
# based on the same debian version as the synapse image, to make sure we get
|
||||
# the expected version of libc.
|
||||
FROM docker.io/library/redis:7-${DEBIAN_VERSION} AS redis_base
|
||||
|
||||
# now build the final image, based on the the regular Synapse docker image
|
||||
FROM $FROM
|
||||
|
||||
# Copy over dependencies
|
||||
COPY --from=redis_base /usr/local/bin/redis-server /usr/local/bin
|
||||
COPY --from=deps_base --parents /usr/lib/*-linux-gnu/libicu* /
|
||||
COPY --from=deps_base /usr/bin/redis-server /usr/local/bin
|
||||
COPY --from=deps_base /uv /
|
||||
COPY --from=deps_base /usr/sbin/nginx /usr/sbin
|
||||
COPY --from=deps_base /usr/share/nginx /usr/share/nginx
|
||||
@@ -65,6 +71,15 @@ FROM $FROM
|
||||
|
||||
# Expose nginx listener port
|
||||
EXPOSE 8080/tcp
|
||||
# Metrics for workers are on ports starting from 19091 but since these are dynamic
|
||||
# we don't expose them by default (metrics must be enabled with
|
||||
# SYNAPSE_ENABLE_METRICS=1)
|
||||
#
|
||||
# Instead, we expose a single port used for Prometheus HTTP service discovery
|
||||
# (`http://<synapse_container>:9469/metrics/service_discovery`) and proxy all of the
|
||||
# workers' metrics endpoints through that
|
||||
# (`http://<synapse_container>:9469/metrics/worker/<worker_name>`).
|
||||
EXPOSE 9469/tcp
|
||||
|
||||
# A script to read environment variables and create the necessary
|
||||
# files to run the desired worker configuration. Will start supervisord.
|
||||
|
||||
@@ -12,11 +12,9 @@ Note that running Synapse's unit tests from within the docker image is not suppo
|
||||
|
||||
`scripts-dev/complement.sh` is a script that will automatically build
|
||||
and run Synapse against Complement.
|
||||
Consult the [contributing guide][guideComplementSh] for instructions on how to use it.
|
||||
Consult our [Complement docs][https://github.com/element-hq/synapse/tree/develop/complement] for instructions on how to use it.
|
||||
|
||||
|
||||
[guideComplementSh]: https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-integration-tests-complement
|
||||
|
||||
## Building and running the images manually
|
||||
|
||||
Under some circumstances, you may wish to build the images manually.
|
||||
@@ -31,23 +29,23 @@ release of Synapse, instead of your current checkout, you can skip this step. Fr
|
||||
root of the repository:
|
||||
|
||||
```sh
|
||||
docker build -t matrixdotorg/synapse -f docker/Dockerfile .
|
||||
docker build -t localhost/synapse -f docker/Dockerfile .
|
||||
```
|
||||
|
||||
Next, build the workerised Synapse docker image, which is a layer over the base
|
||||
image.
|
||||
|
||||
```sh
|
||||
docker build -t matrixdotorg/synapse-workers -f docker/Dockerfile-workers .
|
||||
docker build -t localhost/synapse-workers --build-arg FROM=localhost/synapse -f docker/Dockerfile-workers .
|
||||
```
|
||||
|
||||
Finally, build the multi-purpose image for Complement, which is a layer over the workers image.
|
||||
|
||||
```sh
|
||||
docker build -t complement-synapse -f docker/complement/Dockerfile docker/complement
|
||||
docker build -t localhost/complement-synapse -f docker/complement/Dockerfile --build-arg FROM=localhost/synapse-workers docker/complement
|
||||
```
|
||||
|
||||
This will build an image with the tag `complement-synapse`, which can be handed to
|
||||
This will build an image with the tag `localhost/complement-synapse`, which can be handed to
|
||||
Complement for testing via the `COMPLEMENT_BASE_IMAGE` environment variable. Refer to
|
||||
[Complement's documentation](https://github.com/matrix-org/complement/#running) for
|
||||
how to run the tests, as well as the various available command line flags.
|
||||
@@ -135,3 +133,49 @@ but it does not serve TLS by default.
|
||||
You can configure `SYNAPSE_TLS_CERT` and `SYNAPSE_TLS_KEY` to point to a
|
||||
TLS certificate and key (respectively), both in PEM (textual) format.
|
||||
In this case, Nginx will additionally serve using HTTPS on port 8448.
|
||||
|
||||
|
||||
### Metrics
|
||||
|
||||
Set `SYNAPSE_ENABLE_METRICS=1` to configure `enable_metrics: true` and setup the
|
||||
`metrics` listener on the main and worker processes. Defaults to `0` (disabled). The
|
||||
main process will listen on port `19090` and workers on port `19091 + <worker index>`.
|
||||
|
||||
When using `docker/Dockerfile-workers`, to ease the complexity with the metrics setup,
|
||||
we also have a [Prometheus HTTP service
|
||||
discovery](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#http_sd_config)
|
||||
endpoint available at `http://<synapse_container>:9469/metrics/service_discovery`.
|
||||
|
||||
The metrics from each worker can also be accessed via
|
||||
`http://<synapse_container>:9469/metrics/worker/<worker_name>` which is what the service
|
||||
discovery response points to behind the scenes. This way, you only need to expose a
|
||||
single port (9469) to access all metrics.
|
||||
|
||||
```yaml
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
scrape_timeout: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: synapse
|
||||
scrape_interval: 15s
|
||||
metrics_path: /_synapse/metrics
|
||||
scheme: http
|
||||
# We set `honor_labels` so that each service can set their own `job`/`instance` label
|
||||
#
|
||||
# > honor_labels controls how Prometheus handles conflicts between labels that are
|
||||
# > already present in scraped data and labels that Prometheus would attach
|
||||
# > server-side ("job" and "instance" labels, manually configured target
|
||||
# > labels, and labels generated by service discovery implementations).
|
||||
# >
|
||||
# > *-- https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config*
|
||||
honor_labels: true
|
||||
# Use HTTP service discovery
|
||||
#
|
||||
# Reference:
|
||||
# - https://prometheus.io/docs/prometheus/latest/http_sd/
|
||||
# - https://prometheus.io/docs/prometheus/latest/configuration/configuration/#http_sd_config
|
||||
http_sd_configs:
|
||||
- url: 'http://localhost:9469/metrics/service_discovery'
|
||||
```
|
||||
@@ -75,6 +75,9 @@ The following environment variables are supported in `generate` mode:
|
||||
particularly tricky.
|
||||
* `SYNAPSE_LOG_TESTING`: if set, Synapse will log additional information useful
|
||||
for testing.
|
||||
* `SYNAPSE_ENABLE_METRICS`: if set to `1`, the metrics listener will be enabled on the
|
||||
main and worker processes. Defaults to `0` (disabled). The main process will listen on
|
||||
port `19090` and workers on port `19091 + <worker index>`.
|
||||
|
||||
## Postgres
|
||||
|
||||
|
||||
@@ -9,24 +9,24 @@
|
||||
ARG SYNAPSE_VERSION=latest
|
||||
# This is an intermediate image, to be built locally (not pulled from a registry).
|
||||
ARG FROM=matrixdotorg/synapse-workers:$SYNAPSE_VERSION
|
||||
ARG DEBIAN_VERSION=bookworm
|
||||
ARG DEBIAN_VERSION=trixie
|
||||
|
||||
FROM docker.io/library/postgres:13-${DEBIAN_VERSION} AS postgres_base
|
||||
FROM docker.io/library/postgres:14-${DEBIAN_VERSION} AS postgres_base
|
||||
|
||||
FROM $FROM
|
||||
# First of all, we copy postgres server from the official postgres image,
|
||||
# since for repeated rebuilds, this is much faster than apt installing
|
||||
# postgres each time.
|
||||
|
||||
# This trick only works because (a) the Synapse image happens to have all the
|
||||
# shared libraries that postgres wants, (b) we use a postgres image based on
|
||||
# the same debian version as Synapse's docker image (so the versions of the
|
||||
# shared libraries match).
|
||||
# This trick only works because we use a postgres image based on the same
|
||||
# debian version as Synapse's docker image (so the versions of the shared
|
||||
# libraries match). Any missing libraries need to be added to either the
|
||||
# Synapse image or docker/Dockerfile-workers.
|
||||
RUN adduser --system --uid 999 postgres --home /var/lib/postgresql
|
||||
COPY --from=postgres_base /usr/lib/postgresql /usr/lib/postgresql
|
||||
COPY --from=postgres_base /usr/share/postgresql /usr/share/postgresql
|
||||
COPY --from=postgres_base --chown=postgres /var/run/postgresql /var/run/postgresql
|
||||
ENV PATH="${PATH}:/usr/lib/postgresql/13/bin"
|
||||
ENV PATH="${PATH}:/usr/lib/postgresql/14/bin"
|
||||
ENV PGDATA=/var/lib/postgresql/data
|
||||
|
||||
# We also initialize the database at build time, rather than runtime, so that it's faster to spin up the image.
|
||||
|
||||
@@ -128,6 +128,10 @@ openssl x509 -req -in /conf/server.tls.csr \
|
||||
export SYNAPSE_TLS_CERT=/conf/server.tls.crt
|
||||
export SYNAPSE_TLS_KEY=/conf/server.tls.key
|
||||
|
||||
# Add a directory for tests to add config overrides if they want
|
||||
mkdir --parents /conf/homeserver.d
|
||||
export _SYNAPSE_COMPLEMENT_EXTRA_CONFIG_DIR=/conf/homeserver.d
|
||||
|
||||
# Run the script that writes the necessary config files and starts supervisord, which in turn
|
||||
# starts everything else
|
||||
exec /configure_workers_and_start.py "$@"
|
||||
@@ -102,6 +102,10 @@ rc_room_creation:
|
||||
per_second: 9999
|
||||
burst_count: 9999
|
||||
|
||||
rc_user_directory:
|
||||
per_second: 9999
|
||||
burst_count: 9999
|
||||
|
||||
federation_rr_transactions_per_room_per_second: 9999
|
||||
|
||||
allow_device_name_lookup_over_federation: true
|
||||
@@ -119,8 +123,6 @@ experimental_features:
|
||||
msc3874_enabled: true
|
||||
# no UIA for x-signing upload for the first time
|
||||
msc3967_enabled: true
|
||||
# Expose a room summary for public rooms
|
||||
msc3266_enabled: true
|
||||
# Send to-device messages to application services
|
||||
msc2409_to_device_messages_enabled: true
|
||||
# Allow application services to masquerade devices
|
||||
@@ -135,6 +137,10 @@ experimental_features:
|
||||
msc4155_enabled: true
|
||||
# Thread Subscriptions
|
||||
msc4306_enabled: true
|
||||
# Sticky Events
|
||||
msc4354_enabled: true
|
||||
# `/sync` `state_after`
|
||||
msc4222_enabled: true
|
||||
|
||||
server_notices:
|
||||
system_mxid_localpart: _server
|
||||
|
||||
@@ -48,3 +48,5 @@ server {
|
||||
proxy_set_header Host $host:$server_port;
|
||||
}
|
||||
}
|
||||
|
||||
{{ nginx_prometheus_metrics_service_discovery }}
|
||||
@@ -20,4 +20,9 @@ app_service_config_files:
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
|
||||
{# Controlled by SYNAPSE_ENABLE_METRICS #}
|
||||
{% if enable_metrics %}
|
||||
enable_metrics: true
|
||||
{% endif %}
|
||||
|
||||
{{ shared_worker_config }}
|
||||
@@ -5,10 +5,16 @@ command=/usr/local/bin/python -m synapse.app.complement_fork_starter
|
||||
{{ main_config_path }}
|
||||
synapse.app.homeserver
|
||||
--config-path="{{ main_config_path }}"
|
||||
{%- if extra_config_dir %}
|
||||
--config-path="{{ extra_config_dir }}"
|
||||
{%- endif %}
|
||||
--config-path=/conf/workers/shared.yaml
|
||||
{%- for worker in workers %}
|
||||
-- {{ worker.app }}
|
||||
--config-path="{{ main_config_path }}"
|
||||
{%- if extra_config_dir %}
|
||||
--config-path="{{ extra_config_dir }}"
|
||||
{%- endif %}
|
||||
--config-path=/conf/workers/shared.yaml
|
||||
--config-path=/conf/workers/{{ worker.name }}.yaml
|
||||
{%- endfor %}
|
||||
@@ -24,6 +30,9 @@ exitcodes=0
|
||||
environment=http_proxy="%(ENV_SYNAPSE_HTTP_PROXY)s",https_proxy="%(ENV_SYNAPSE_HTTPS_PROXY)s",no_proxy="%(ENV_SYNAPSE_NO_PROXY)s"
|
||||
command=/usr/local/bin/prefix-log /usr/local/bin/python -m synapse.app.homeserver
|
||||
--config-path="{{ main_config_path }}"
|
||||
{%- if extra_config_dir %}
|
||||
--config-path="{{ extra_config_dir }}"
|
||||
{%- endif %}
|
||||
--config-path=/conf/workers/shared.yaml
|
||||
priority=10
|
||||
# Log startup failures to supervisord's stdout/err
|
||||
|
||||
@@ -21,6 +21,14 @@ worker_listeners:
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
|
||||
{# Controlled by SYNAPSE_ENABLE_METRICS #}
|
||||
{% if metrics_port %}
|
||||
- type: metrics
|
||||
# Prometheus does not support Unix sockets so we don't bother with
|
||||
# `SYNAPSE_USE_UNIX_SOCKET`, https://github.com/prometheus/prometheus/issues/12024
|
||||
port: {{ metrics_port }}
|
||||
{% endif %}
|
||||
|
||||
worker_log_config: {{ worker_log_config_filepath }}
|
||||
|
||||
{{ worker_extra_conf }}
|
||||
@@ -53,6 +53,15 @@ listeners:
|
||||
- names: [federation]
|
||||
compress: false
|
||||
|
||||
{% if SYNAPSE_ENABLE_METRICS %}
|
||||
- type: metrics
|
||||
# The main process always uses the same port 19090
|
||||
#
|
||||
# Prometheus does not support Unix sockets so we don't bother with
|
||||
# `SYNAPSE_USE_UNIX_SOCKET`, https://github.com/prometheus/prometheus/issues/12024
|
||||
port: 19090
|
||||
{% endif %}
|
||||
|
||||
## Database ##
|
||||
|
||||
{% if POSTGRES_PASSWORD %}
|
||||
|
||||
@@ -49,11 +49,16 @@
|
||||
# regardless of the SYNAPSE_LOG_LEVEL setting.
|
||||
# * SYNAPSE_LOG_TESTING: if set, Synapse will log additional information useful
|
||||
# for testing.
|
||||
# * SYNAPSE_USE_UNIX_SOCKET: TODO
|
||||
# * `SYNAPSE_ENABLE_METRICS`: if set to `1`, the metrics listener will be enabled on the
|
||||
# main and worker processes. Defaults to `0` (disabled). The main process will listen on
|
||||
# port `19090` and workers on port `19091 + <worker index>`.
|
||||
#
|
||||
# NOTE: According to Complement's ENTRYPOINT expectations for a homeserver image (as defined
|
||||
# in the project's README), this script may be run multiple times, and functionality should
|
||||
# continue to work if so.
|
||||
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
@@ -65,16 +70,13 @@ from itertools import chain
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
NoReturn,
|
||||
Optional,
|
||||
Set,
|
||||
SupportsIndex,
|
||||
)
|
||||
|
||||
import attr
|
||||
import yaml
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
@@ -96,7 +98,7 @@ WORKER_PLACEHOLDER_NAME = "placeholder_name"
|
||||
# Watching /_matrix/media and related needs a "media" listener
|
||||
# Stream Writers require "client" and "replication" listeners because they
|
||||
# have to attach by instance_map to the master process and have client endpoints.
|
||||
WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
|
||||
WORKERS_CONFIG: dict[str, dict[str, Any]] = {
|
||||
"pusher": {
|
||||
"app": "synapse.app.generic_worker",
|
||||
"listener_resources": [],
|
||||
@@ -117,7 +119,7 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
|
||||
},
|
||||
"media_repository": {
|
||||
"app": "synapse.app.generic_worker",
|
||||
"listener_resources": ["media", "client"],
|
||||
"listener_resources": ["media", "client", "replication"],
|
||||
"endpoint_patterns": [
|
||||
"^/_matrix/media/",
|
||||
"^/_synapse/admin/v1/purge_media_cache$",
|
||||
@@ -200,6 +202,7 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
|
||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/keys/upload",
|
||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/keys/device_signing/upload$",
|
||||
"^/_matrix/client/(api/v1|r0|v3|unstable)/keys/signatures/upload$",
|
||||
"^/_matrix/client/unstable/org.matrix.msc4140/delayed_events(/.*/restart)?$",
|
||||
],
|
||||
"shared_extra_conf": {},
|
||||
"worker_extra_conf": "",
|
||||
@@ -340,7 +343,7 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
|
||||
}
|
||||
|
||||
# Templates for sections that may be inserted multiple times in config files
|
||||
NGINX_LOCATION_CONFIG_BLOCK = """
|
||||
NGINX_LOCATION_REGEX_CONFIG_BLOCK = """
|
||||
location ~* {endpoint} {{
|
||||
proxy_pass {upstream};
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
@@ -349,6 +352,25 @@ NGINX_LOCATION_CONFIG_BLOCK = """
|
||||
}}
|
||||
"""
|
||||
|
||||
# Having both **regex** (`NGINX_LOCATION_REGEX_CONFIG_BLOCK`) match vs **exact**
|
||||
# (`NGINX_LOCATION_EXACT_CONFIG_BLOCK`) match is necessary because we can't use a URI
|
||||
# path in `proxy_pass http://localhost:19090/_synapse/metrics` with the regex version.
|
||||
#
|
||||
# Example of what happens if you try to use `proxy_pass http://localhost:19090/_synapse/metrics`
|
||||
# with `NGINX_LOCATION_REGEX_CONFIG_BLOCK`:
|
||||
# ```
|
||||
# nginx | 2025/12/31 22:58:34 [emerg] 21#21: "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/conf.d/matrix-synapse.conf:732
|
||||
# ```
|
||||
NGINX_LOCATION_EXACT_CONFIG_BLOCK = """
|
||||
location = {endpoint} {{
|
||||
proxy_pass {upstream};
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
NGINX_UPSTREAM_CONFIG_BLOCK = """
|
||||
upstream {upstream_worker_base_name} {{
|
||||
{body}
|
||||
@@ -356,6 +378,63 @@ upstream {upstream_worker_base_name} {{
|
||||
"""
|
||||
|
||||
|
||||
PROMETHEUS_METRICS_SERVICE_DISCOVERY_FILE_PATH = (
|
||||
"/data/prometheus_service_discovery.json"
|
||||
)
|
||||
"""
|
||||
We serve this file with nginx so people can use it with `http_sd_config` in their
|
||||
Prometheus config.
|
||||
"""
|
||||
|
||||
NGINX_HOST_PLACEHOLDER = "<HOST_PLACEHOLDER>"
|
||||
"""Will be replaced with the whatever hostname:port used to access the nginx metrics endpoint."""
|
||||
|
||||
NGINX_PROMETHEUS_METRICS_SERVICE_DISCOVERY = """
|
||||
server {{
|
||||
listen 9469;
|
||||
location = /metrics/service_discovery {{
|
||||
alias {service_discovery_file_path};
|
||||
default_type application/json;
|
||||
|
||||
# Find/replace the host placeholder in the response body with the actual
|
||||
# host used to access this endpoint.
|
||||
#
|
||||
# We want to reflect back whatever host the client used to access this file.
|
||||
# For example, if they accessed it via `localhost:9469`, then they
|
||||
# can also reach all of the proxied metrics endpoints at the same address.
|
||||
# Or if it's Prometheus in another container, it will access this via
|
||||
# `host.docker.internal:9469`, etc. Or perhaps it's even some randomly assigned
|
||||
# port mapping.
|
||||
sub_filter '{host_placeholder}' '$http_host';
|
||||
# By default, `ngx_http_sub_module` only works on `text/html` responses. We want
|
||||
# to find/replace in `application/JSON`.
|
||||
sub_filter_types application/json;
|
||||
# Replace all occurences
|
||||
sub_filter_once off;
|
||||
}}
|
||||
|
||||
# Make the service discovery endpoint easy to find; redirect to the correct spot.
|
||||
location = / {{
|
||||
return 302 /metrics/service_discovery;
|
||||
}}
|
||||
|
||||
{metrics_proxy_locations}
|
||||
}}
|
||||
"""
|
||||
"""
|
||||
Setup the nginx config necessary to serve the JSON file for Prometheus HTTP service discovery
|
||||
(`http_sd_config`). Served at `/metrics/service_discovery`.
|
||||
|
||||
Reference:
|
||||
- https://prometheus.io/docs/prometheus/latest/http_sd/
|
||||
- https://prometheus.io/docs/prometheus/latest/configuration/configuration/#http_sd_config
|
||||
|
||||
We also proxy all of the Synapse metrics endpoints through a central place so that
|
||||
people only need to expose the single 9469 port and service discovery can take care of
|
||||
the rest: `/metrics/worker/<worker_name>` -> http://localhost:19090/_synapse/metrics
|
||||
"""
|
||||
|
||||
|
||||
# Utility functions
|
||||
def log(txt: str) -> None:
|
||||
print(txt)
|
||||
@@ -408,7 +487,7 @@ def convert(src: str, dst: str, **template_vars: object) -> None:
|
||||
|
||||
def add_worker_roles_to_shared_config(
|
||||
shared_config: dict,
|
||||
worker_types_set: Set[str],
|
||||
worker_types_set: set[str],
|
||||
worker_name: str,
|
||||
worker_port: int,
|
||||
) -> None:
|
||||
@@ -471,9 +550,9 @@ def add_worker_roles_to_shared_config(
|
||||
|
||||
|
||||
def merge_worker_template_configs(
|
||||
existing_dict: Optional[Dict[str, Any]],
|
||||
to_be_merged_dict: Dict[str, Any],
|
||||
) -> Dict[str, Any]:
|
||||
existing_dict: dict[str, Any] | None,
|
||||
to_be_merged_dict: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""When given an existing dict of worker template configuration consisting with both
|
||||
dicts and lists, merge new template data from WORKERS_CONFIG(or create) and
|
||||
return new dict.
|
||||
@@ -484,7 +563,7 @@ def merge_worker_template_configs(
|
||||
existing_dict.
|
||||
Returns: The newly merged together dict values.
|
||||
"""
|
||||
new_dict: Dict[str, Any] = {}
|
||||
new_dict: dict[str, Any] = {}
|
||||
if not existing_dict:
|
||||
# It doesn't exist yet, just use the new dict(but take a copy not a reference)
|
||||
new_dict = to_be_merged_dict.copy()
|
||||
@@ -509,8 +588,8 @@ def merge_worker_template_configs(
|
||||
|
||||
|
||||
def insert_worker_name_for_worker_config(
|
||||
existing_dict: Dict[str, Any], worker_name: str
|
||||
) -> Dict[str, Any]:
|
||||
existing_dict: dict[str, Any], worker_name: str
|
||||
) -> dict[str, Any]:
|
||||
"""Insert a given worker name into the worker's configuration dict.
|
||||
|
||||
Args:
|
||||
@@ -526,7 +605,7 @@ def insert_worker_name_for_worker_config(
|
||||
return dict_to_edit
|
||||
|
||||
|
||||
def apply_requested_multiplier_for_worker(worker_types: List[str]) -> List[str]:
|
||||
def apply_requested_multiplier_for_worker(worker_types: list[str]) -> list[str]:
|
||||
"""
|
||||
Apply multiplier(if found) by returning a new expanded list with some basic error
|
||||
checking.
|
||||
@@ -587,7 +666,7 @@ def is_sharding_allowed_for_worker_type(worker_type: str) -> bool:
|
||||
|
||||
def split_and_strip_string(
|
||||
given_string: str, split_char: str, max_split: SupportsIndex = -1
|
||||
) -> List[str]:
|
||||
) -> list[str]:
|
||||
"""
|
||||
Helper to split a string on split_char and strip whitespace from each end of each
|
||||
element.
|
||||
@@ -615,9 +694,42 @@ def generate_base_homeserver_config() -> None:
|
||||
subprocess.run([sys.executable, "/start.py", "migrate_config"], check=True)
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Worker:
|
||||
worker_name: str
|
||||
"""
|
||||
ex.
|
||||
`event_persister:2` -> `event_persister1` and `event_persister2`
|
||||
`stream_writers=account_data+presence+receipts+to_device+typing"` -> `stream_writers`
|
||||
"""
|
||||
|
||||
worker_base_name: str
|
||||
"""
|
||||
ex.
|
||||
`event_persister:2` -> `event_persister`
|
||||
`stream_writers=account_data+presence+receipts+to_device+typing"` -> `stream_writers`
|
||||
"""
|
||||
|
||||
worker_index: int
|
||||
"""
|
||||
The index of the worker starting from 1 for each worker type requested.
|
||||
|
||||
ex.
|
||||
`event_persister:2` -> `1` and `2`
|
||||
`stream_writers=account_data+presence+receipts+to_device+typing"` -> `1`
|
||||
"""
|
||||
|
||||
worker_types: set[str]
|
||||
"""
|
||||
ex.
|
||||
`event_persister:2` -> `{"event_persister"}`
|
||||
`stream_writers=account_data+presence+receipts+to_device+typing"` -> `{"account_data", "presence", "receipts","to_device", "typing"}
|
||||
"""
|
||||
|
||||
|
||||
def parse_worker_types(
|
||||
requested_worker_types: List[str],
|
||||
) -> Dict[str, Set[str]]:
|
||||
requested_worker_types: list[str],
|
||||
) -> list[Worker]:
|
||||
"""Read the desired list of requested workers and prepare the data for use in
|
||||
generating worker config files while also checking for potential gotchas.
|
||||
|
||||
@@ -625,22 +737,19 @@ def parse_worker_types(
|
||||
requested_worker_types: The list formed from the split environment variable
|
||||
containing the unprocessed requests for workers.
|
||||
|
||||
Returns: A dict of worker names to set of worker types. Format:
|
||||
{'worker_name':
|
||||
{'worker_type', 'worker_type2'}
|
||||
}
|
||||
Returns: A list of requested workers
|
||||
"""
|
||||
# A counter of worker_base_name -> int. Used for determining the name for a given
|
||||
# worker when generating its config file, as each worker's name is just
|
||||
# worker_base_name followed by instance number
|
||||
worker_base_name_counter: Dict[str, int] = defaultdict(int)
|
||||
worker_base_name_counter: dict[str, int] = defaultdict(int)
|
||||
|
||||
# Similar to above, but more finely grained. This is used to determine we don't have
|
||||
# more than a single worker for cases where multiples would be bad(e.g. presence).
|
||||
worker_type_shard_counter: Dict[str, int] = defaultdict(int)
|
||||
worker_type_shard_counter: dict[str, int] = defaultdict(int)
|
||||
|
||||
# The final result of all this processing
|
||||
dict_to_return: Dict[str, Set[str]] = {}
|
||||
# Map from worker name to `Worker`
|
||||
worker_dict: dict[str, Worker] = {}
|
||||
|
||||
# Handle any multipliers requested for given workers.
|
||||
multiple_processed_worker_types = apply_requested_multiplier_for_worker(
|
||||
@@ -684,7 +793,7 @@ def parse_worker_types(
|
||||
|
||||
# Split the worker_type_string on "+", remove whitespace from ends then make
|
||||
# the list a set so it's deduplicated.
|
||||
worker_types_set: Set[str] = set(
|
||||
worker_types_set: set[str] = set(
|
||||
split_and_strip_string(worker_type_string, "+")
|
||||
)
|
||||
|
||||
@@ -726,24 +835,30 @@ def parse_worker_types(
|
||||
if worker_number > 1:
|
||||
# If this isn't the first worker, check that we don't have a confusing
|
||||
# mixture of worker types with the same base name.
|
||||
first_worker_with_base_name = dict_to_return[f"{worker_base_name}1"]
|
||||
if first_worker_with_base_name != worker_types_set:
|
||||
first_worker_with_base_name = worker_dict[f"{worker_base_name}1"]
|
||||
if first_worker_with_base_name.worker_types != worker_types_set:
|
||||
error(
|
||||
f"Can not use worker_name: '{worker_name}' for worker_type(s): "
|
||||
f"{worker_types_set!r}. It is already in use by "
|
||||
f"worker_type(s): {first_worker_with_base_name!r}"
|
||||
f"worker_type(s): {first_worker_with_base_name.worker_types!r}"
|
||||
)
|
||||
|
||||
dict_to_return[worker_name] = worker_types_set
|
||||
worker_dict[worker_name] = Worker(
|
||||
worker_name=worker_name,
|
||||
worker_base_name=worker_base_name,
|
||||
worker_index=worker_number,
|
||||
worker_types=worker_types_set,
|
||||
)
|
||||
|
||||
return dict_to_return
|
||||
return list(worker_dict.values())
|
||||
|
||||
|
||||
def generate_worker_files(
|
||||
environ: Mapping[str, str],
|
||||
config_path: str,
|
||||
extra_config_dir: str | None,
|
||||
data_dir: str,
|
||||
requested_worker_types: Dict[str, Set[str]],
|
||||
requested_workers: list[Worker],
|
||||
) -> None:
|
||||
"""Read the desired workers(if any) that is passed in and generate shared
|
||||
homeserver, nginx and supervisord configs.
|
||||
@@ -751,20 +866,23 @@ def generate_worker_files(
|
||||
Args:
|
||||
environ: os.environ instance.
|
||||
config_path: The location of the generated Synapse main worker config file.
|
||||
extra_config_dir: A directory in which extra Synapse configuration files will be loaded.
|
||||
data_dir: The location of the synapse data directory. Where log and
|
||||
user-facing config files live.
|
||||
requested_worker_types: A Dict containing requested workers in the format of
|
||||
{'worker_name1': {'worker_type', ...}}
|
||||
requested_workers: A list of requested workers
|
||||
"""
|
||||
# Note that yaml cares about indentation, so care should be taken to insert lines
|
||||
# into files at the correct indentation below.
|
||||
|
||||
# Convenience helper for if using unix sockets instead of host:port
|
||||
using_unix_sockets = environ.get("SYNAPSE_USE_UNIX_SOCKET", False)
|
||||
|
||||
enable_metrics = environ.get("SYNAPSE_ENABLE_METRICS", "0") == "1"
|
||||
|
||||
# First read the original config file and extract the listeners block. Then we'll
|
||||
# add another listener for replication. Later we'll write out the result to the
|
||||
# shared config file.
|
||||
listeners: List[Any]
|
||||
listeners: list[Any]
|
||||
if using_unix_sockets:
|
||||
listeners = [
|
||||
{
|
||||
@@ -792,12 +910,16 @@ def generate_worker_files(
|
||||
# base shared worker jinja2 template. This config file will be passed to all
|
||||
# workers, included Synapse's main process. It is intended mainly for disabling
|
||||
# functionality when certain workers are spun up, and adding a replication listener.
|
||||
shared_config: Dict[str, Any] = {"listeners": listeners}
|
||||
shared_config: dict[str, Any] = {
|
||||
"listeners": listeners,
|
||||
# Controls `enable_metrics: true`
|
||||
"enable_metrics": enable_metrics,
|
||||
}
|
||||
|
||||
# List of dicts that describe workers.
|
||||
# We pass this to the Supervisor template later to generate the appropriate
|
||||
# program blocks.
|
||||
worker_descriptors: List[Dict[str, Any]] = []
|
||||
worker_descriptors: list[dict[str, Any]] = []
|
||||
|
||||
# Upstreams for load-balancing purposes. This dict takes the form of the worker
|
||||
# type to the ports of each worker. For example:
|
||||
@@ -805,20 +927,22 @@ def generate_worker_files(
|
||||
# worker_type: {1234, 1235, ...}}
|
||||
# }
|
||||
# and will be used to construct 'upstream' nginx directives.
|
||||
nginx_upstreams: Dict[str, Set[int]] = {}
|
||||
nginx_upstreams: dict[str, set[int]] = {}
|
||||
|
||||
# A map of: {"endpoint": "upstream"}, where "upstream" is a str representing what
|
||||
# will be placed after the proxy_pass directive. The main benefit to representing
|
||||
# this data as a dict over a str is that we can easily deduplicate endpoints
|
||||
# across multiple instances of the same worker. The final rendering will be combined
|
||||
# with nginx_upstreams and placed in /etc/nginx/conf.d.
|
||||
nginx_locations: Dict[str, str] = {}
|
||||
nginx_locations: dict[str, str] = {}
|
||||
|
||||
# Create the worker configuration directory if it doesn't already exist
|
||||
os.makedirs("/conf/workers", exist_ok=True)
|
||||
|
||||
# Start worker ports from this arbitrary port
|
||||
worker_port = 18009
|
||||
# The main process metrics port is 19090, so start workers from 19091
|
||||
worker_metrics_port = 19091
|
||||
|
||||
# A list of internal endpoints to healthcheck, starting with the main process
|
||||
# which exists even if no workers do.
|
||||
@@ -835,7 +959,9 @@ def generate_worker_files(
|
||||
healthcheck_urls = ["http://localhost:8080/health"]
|
||||
|
||||
# Get the set of all worker types that we have configured
|
||||
all_worker_types_in_use = set(chain(*requested_worker_types.values()))
|
||||
all_worker_types_in_use = set(
|
||||
chain(*[worker.worker_types for worker in requested_workers])
|
||||
)
|
||||
# Map locations to upstreams (corresponding to worker types) in Nginx
|
||||
# but only if we use the appropriate worker type
|
||||
for worker_type in all_worker_types_in_use:
|
||||
@@ -844,12 +970,13 @@ def generate_worker_files(
|
||||
|
||||
# For each worker type specified by the user, create config values and write it's
|
||||
# yaml config file
|
||||
for worker_name, worker_types_set in requested_worker_types.items():
|
||||
worker_name_to_metrics_port_map: dict[str, int] = {}
|
||||
for worker in requested_workers:
|
||||
# The collected and processed data will live here.
|
||||
worker_config: Dict[str, Any] = {}
|
||||
worker_config: dict[str, Any] = {}
|
||||
|
||||
# Merge all worker config templates for this worker into a single config
|
||||
for worker_type in worker_types_set:
|
||||
for worker_type in worker.worker_types:
|
||||
copy_of_template_config = WORKERS_CONFIG[worker_type].copy()
|
||||
|
||||
# Merge worker type template configuration data. It's a combination of lists
|
||||
@@ -859,16 +986,27 @@ def generate_worker_files(
|
||||
)
|
||||
|
||||
# Replace placeholder names in the config template with the actual worker name.
|
||||
worker_config = insert_worker_name_for_worker_config(worker_config, worker_name)
|
||||
|
||||
worker_config.update(
|
||||
{"name": worker_name, "port": str(worker_port), "config_path": config_path}
|
||||
worker_config = insert_worker_name_for_worker_config(
|
||||
worker_config, worker.worker_name
|
||||
)
|
||||
|
||||
# Update the shared config with any worker_type specific options. The first of a
|
||||
# given worker_type needs to stay assigned and not be replaced.
|
||||
worker_config["shared_extra_conf"].update(shared_config)
|
||||
shared_config = worker_config["shared_extra_conf"]
|
||||
worker_config.update(
|
||||
{
|
||||
"name": worker.worker_name,
|
||||
"port": str(worker_port),
|
||||
"config_path": config_path,
|
||||
}
|
||||
)
|
||||
|
||||
# Keep the `shared_config` up to date with the `shared_extra_conf` from each
|
||||
# worker.
|
||||
shared_config = {
|
||||
**worker_config["shared_extra_conf"],
|
||||
# We combine `shared_config` second to avoid overwriting existing keys just
|
||||
# for sanity sake (always use the first worker).
|
||||
**shared_config,
|
||||
}
|
||||
|
||||
if using_unix_sockets:
|
||||
healthcheck_urls.append(
|
||||
f"--unix-socket /run/worker.{worker_port} http://localhost/health"
|
||||
@@ -880,39 +1018,51 @@ def generate_worker_files(
|
||||
# the `events` stream. For other workers, the worker name is the same
|
||||
# name of the stream they write to, but for some reason it is not the
|
||||
# case for event_persister.
|
||||
if "event_persister" in worker_types_set:
|
||||
worker_types_set.add("events")
|
||||
if "event_persister" in worker.worker_types:
|
||||
worker.worker_types.add("events")
|
||||
|
||||
# Update the shared config with sharding-related options if necessary
|
||||
add_worker_roles_to_shared_config(
|
||||
shared_config, worker_types_set, worker_name, worker_port
|
||||
shared_config, worker.worker_types, worker.worker_name, worker_port
|
||||
)
|
||||
|
||||
# Enable the worker in supervisord
|
||||
worker_descriptors.append(worker_config)
|
||||
|
||||
# Write out the worker's logging config file
|
||||
log_config_filepath = generate_worker_log_config(environ, worker_name, data_dir)
|
||||
log_config_filepath = generate_worker_log_config(
|
||||
environ, worker.worker_name, data_dir
|
||||
)
|
||||
|
||||
worker_name_to_metrics_port_map[worker.worker_name] = worker_metrics_port
|
||||
if enable_metrics:
|
||||
# Enable prometheus metrics endpoint on this worker
|
||||
worker_config["metrics_port"] = worker_metrics_port
|
||||
|
||||
if enable_metrics:
|
||||
# Enable prometheus metrics endpoint on this worker
|
||||
worker_config["metrics_port"] = worker_metrics_port
|
||||
|
||||
# Then a worker config file
|
||||
convert(
|
||||
"/conf/worker.yaml.j2",
|
||||
f"/conf/workers/{worker_name}.yaml",
|
||||
f"/conf/workers/{worker.worker_name}.yaml",
|
||||
**worker_config,
|
||||
worker_log_config_filepath=log_config_filepath,
|
||||
using_unix_sockets=using_unix_sockets,
|
||||
)
|
||||
|
||||
# Save this worker's port number to the correct nginx upstreams
|
||||
for worker_type in worker_types_set:
|
||||
for worker_type in worker.worker_types:
|
||||
nginx_upstreams.setdefault(worker_type, set()).add(worker_port)
|
||||
|
||||
worker_port += 1
|
||||
worker_metrics_port += 1
|
||||
|
||||
# Build the nginx location config blocks
|
||||
nginx_location_config = ""
|
||||
for endpoint, upstream in nginx_locations.items():
|
||||
nginx_location_config += NGINX_LOCATION_CONFIG_BLOCK.format(
|
||||
nginx_location_config += NGINX_LOCATION_REGEX_CONFIG_BLOCK.format(
|
||||
endpoint=endpoint,
|
||||
upstream=upstream,
|
||||
)
|
||||
@@ -920,14 +1070,21 @@ def generate_worker_files(
|
||||
# Determine the load-balancing upstreams to configure
|
||||
nginx_upstream_config = ""
|
||||
for upstream_worker_base_name, upstream_worker_ports in nginx_upstreams.items():
|
||||
# We use `max_fails=0` to prevent nginx from marking an upstream as unavailable
|
||||
# after it fails to contact the Synapse worker. Otherwise, if nginx sees a
|
||||
# Synapse worker as unavailable once, it will be marked as unavailable for 10
|
||||
# seconds (`fail_timeout` default).
|
||||
#
|
||||
# This is necessary because we use `COMPLEMENT_ENABLE_DIRTY_RUNS` (re-uses
|
||||
# deployments/homeservers) and we don't want any cross-test pollution from
|
||||
# stopping/starting homeservers.
|
||||
body = ""
|
||||
if using_unix_sockets:
|
||||
for port in upstream_worker_ports:
|
||||
body += f" server unix:/run/worker.{port};\n"
|
||||
|
||||
body += f" server unix:/run/worker.{port} max_fails=0;\n"
|
||||
else:
|
||||
for port in upstream_worker_ports:
|
||||
body += f" server localhost:{port};\n"
|
||||
body += f" server localhost:{port} max_fails=0;\n"
|
||||
|
||||
# Add to the list of configured upstreams
|
||||
nginx_upstream_config += NGINX_UPSTREAM_CONFIG_BLOCK.format(
|
||||
@@ -935,6 +1092,111 @@ def generate_worker_files(
|
||||
body=body,
|
||||
)
|
||||
|
||||
# Provide a Prometheus metrics service discovery endpoint to easily be able to pick
|
||||
# up all of the workers
|
||||
nginx_prometheus_metrics_service_discovery = ""
|
||||
if enable_metrics:
|
||||
# Write JSON file for Prometheus service discovery pointing to all of the
|
||||
# workers. We serve this file with nginx so people can use it with
|
||||
# `http_sd_config` in their Prometheus config.
|
||||
#
|
||||
# > It fetches targets from an HTTP endpoint containing a list of zero or more
|
||||
# > `<static_config>`s. The target must reply with an HTTP 200 response. The HTTP
|
||||
# > header `Content-Type` must be `application/json`, and the body must be valid
|
||||
# > JSON.
|
||||
# >
|
||||
# > *-- https://prometheus.io/docs/prometheus/latest/configuration/configuration/#http_sd_config*
|
||||
#
|
||||
# Another reference: https://prometheus.io/docs/prometheus/latest/http_sd/
|
||||
prometheus_http_service_discovery_content = [
|
||||
{
|
||||
"targets": [NGINX_HOST_PLACEHOLDER],
|
||||
"labels": {
|
||||
# The downstream user should also configure `honor_labels: true` in
|
||||
# their Prometheus config to prevent Prometheus from overwriting the
|
||||
# `job` labels.
|
||||
#
|
||||
# > honor_labels controls how Prometheus handles conflicts between labels that are
|
||||
# > already present in scraped data and labels that Prometheus would attach
|
||||
# > server-side ("job" and "instance" labels, manually configured target
|
||||
# > labels, and labels generated by service discovery implementations).
|
||||
# >
|
||||
# > *-- https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config*
|
||||
#
|
||||
# Reference:
|
||||
# - https://prometheus.io/docs/concepts/jobs_instances/
|
||||
# - https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config
|
||||
"job": worker.worker_base_name,
|
||||
"index": f"{worker.worker_index}",
|
||||
# This allows us to change the `metrics_path` on a per-target basis.
|
||||
# We want to grab the metrics from our nginx proxied location (setup
|
||||
# below).
|
||||
#
|
||||
# While there doesn't seem to be official docs on these special
|
||||
# labels (`__metrics_path__`, `__scheme__`, `__scrape_interval__`,
|
||||
# `__scrape_timeout__`), this discussion best summarizes how this
|
||||
# works: https://github.com/prometheus/prometheus/discussions/13217
|
||||
"__metrics_path__": f"/metrics/worker/{worker.worker_name}",
|
||||
},
|
||||
}
|
||||
for worker in requested_workers
|
||||
]
|
||||
# Add the main Synapse process as well
|
||||
prometheus_http_service_discovery_content.append(
|
||||
{
|
||||
"targets": [NGINX_HOST_PLACEHOLDER],
|
||||
"labels": {
|
||||
# We use `"synapse"` as the job name for the main process because it
|
||||
# matches what we expect people to use from a monolith setup with
|
||||
# their static scrape config. It's `job` name used in our Grafana
|
||||
# dashboard for the main process.
|
||||
"job": "synapse",
|
||||
"index": "1",
|
||||
"__metrics_path__": "/metrics/worker/main",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Check to make sure the file doesn't already exist
|
||||
if os.path.isfile(PROMETHEUS_METRICS_SERVICE_DISCOVERY_FILE_PATH):
|
||||
error(
|
||||
f"Prometheus service discovery file "
|
||||
f"'{PROMETHEUS_METRICS_SERVICE_DISCOVERY_FILE_PATH}' already exists (unexpected)! "
|
||||
f"This is a problem because the existing file probably doesn't match the "
|
||||
"Synapse workers we're setting up now."
|
||||
)
|
||||
|
||||
# Write the file
|
||||
with open(PROMETHEUS_METRICS_SERVICE_DISCOVERY_FILE_PATH, "w") as outfile:
|
||||
outfile.write(
|
||||
json.dumps(prometheus_http_service_discovery_content, indent=4)
|
||||
)
|
||||
|
||||
# Proxy all of the Synapse metrics endpoints through a central place so that
|
||||
# people only need to expose the single 9469 port and service discovery can take
|
||||
# care of the rest: `/metrics/worker/<worker_name>` ->
|
||||
# http://localhost:19090/_synapse/metrics
|
||||
#
|
||||
# Build the nginx location config blocks
|
||||
metrics_proxy_locations = ""
|
||||
for worker in requested_workers:
|
||||
metrics_proxy_locations += NGINX_LOCATION_EXACT_CONFIG_BLOCK.format(
|
||||
endpoint=f"/metrics/worker/{worker.worker_name}",
|
||||
upstream=f"http://localhost:{worker_name_to_metrics_port_map[worker.worker_name]}/_synapse/metrics",
|
||||
)
|
||||
# Add the main Synapse process as well
|
||||
metrics_proxy_locations += NGINX_LOCATION_EXACT_CONFIG_BLOCK.format(
|
||||
endpoint="/metrics/worker/main",
|
||||
upstream="http://localhost:19090/_synapse/metrics",
|
||||
)
|
||||
|
||||
# Add a nginx server/location to serve the JSON file
|
||||
nginx_prometheus_metrics_service_discovery = NGINX_PROMETHEUS_METRICS_SERVICE_DISCOVERY.format(
|
||||
service_discovery_file_path=PROMETHEUS_METRICS_SERVICE_DISCOVERY_FILE_PATH,
|
||||
host_placeholder=NGINX_HOST_PLACEHOLDER,
|
||||
metrics_proxy_locations=metrics_proxy_locations,
|
||||
)
|
||||
|
||||
# Finally, we'll write out the config files.
|
||||
|
||||
# log config for the master process
|
||||
@@ -952,7 +1214,7 @@ def generate_worker_files(
|
||||
if reg_path.suffix.lower() in (".yaml", ".yml")
|
||||
]
|
||||
|
||||
workers_in_use = len(requested_worker_types) > 0
|
||||
workers_in_use = len(requested_workers) > 0
|
||||
|
||||
# If there are workers, add the main process to the instance_map too.
|
||||
if workers_in_use:
|
||||
@@ -987,6 +1249,7 @@ def generate_worker_files(
|
||||
tls_cert_path=os.environ.get("SYNAPSE_TLS_CERT"),
|
||||
tls_key_path=os.environ.get("SYNAPSE_TLS_KEY"),
|
||||
using_unix_sockets=using_unix_sockets,
|
||||
nginx_prometheus_metrics_service_discovery=nginx_prometheus_metrics_service_discovery,
|
||||
)
|
||||
|
||||
# Supervisord config
|
||||
@@ -1004,6 +1267,7 @@ def generate_worker_files(
|
||||
"/etc/supervisor/conf.d/synapse.conf",
|
||||
workers=worker_descriptors,
|
||||
main_config_path=config_path,
|
||||
extra_config_dir=extra_config_dir,
|
||||
use_forking_launcher=environ.get("SYNAPSE_USE_EXPERIMENTAL_FORKING_LAUNCHER"),
|
||||
)
|
||||
|
||||
@@ -1029,7 +1293,7 @@ def generate_worker_log_config(
|
||||
Returns: the path to the generated file
|
||||
"""
|
||||
# Check whether we should write worker logs to disk, in addition to the console
|
||||
extra_log_template_args: Dict[str, Optional[str]] = {}
|
||||
extra_log_template_args: dict[str, str | None] = {}
|
||||
if environ.get("SYNAPSE_WORKERS_WRITE_LOGS_TO_DISK"):
|
||||
extra_log_template_args["LOG_FILE_PATH"] = f"{data_dir}/logs/{worker_name}.log"
|
||||
|
||||
@@ -1053,7 +1317,7 @@ def generate_worker_log_config(
|
||||
return log_config_filepath
|
||||
|
||||
|
||||
def main(args: List[str], environ: MutableMapping[str, str]) -> None:
|
||||
def main(args: list[str], environ: MutableMapping[str, str]) -> None:
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--generate-only",
|
||||
@@ -1064,6 +1328,9 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
|
||||
|
||||
config_dir = environ.get("SYNAPSE_CONFIG_DIR", "/data")
|
||||
config_path = environ.get("SYNAPSE_CONFIG_PATH", config_dir + "/homeserver.yaml")
|
||||
# All files in this directory will be loaded as `homeserver.yaml` snippets
|
||||
# Currently only intended for use by Complement
|
||||
extra_config_dir = environ.get("_SYNAPSE_COMPLEMENT_EXTRA_CONFIG_DIR", None)
|
||||
data_dir = environ.get("SYNAPSE_DATA_DIR", "/data")
|
||||
|
||||
# override SYNAPSE_NO_TLS, we don't support TLS in worker mode,
|
||||
@@ -1087,15 +1354,21 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
|
||||
if not worker_types_env:
|
||||
# No workers, just the main process
|
||||
worker_types = []
|
||||
requested_worker_types: Dict[str, Any] = {}
|
||||
requested_workers: list[Worker] = []
|
||||
else:
|
||||
# Split type names by comma, ignoring whitespace.
|
||||
worker_types = split_and_strip_string(worker_types_env, ",")
|
||||
requested_worker_types = parse_worker_types(worker_types)
|
||||
requested_workers = parse_worker_types(worker_types)
|
||||
|
||||
# Always regenerate all other config files
|
||||
log("Generating worker config files")
|
||||
generate_worker_files(environ, config_path, data_dir, requested_worker_types)
|
||||
generate_worker_files(
|
||||
environ=environ,
|
||||
config_path=config_path,
|
||||
extra_config_dir=extra_config_dir,
|
||||
data_dir=data_dir,
|
||||
requested_workers=requested_workers,
|
||||
)
|
||||
|
||||
# Mark workers as being configured
|
||||
with open(mark_filepath, "w") as f:
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
#
|
||||
# Used by `complement.sh`. Not suitable for production use.
|
||||
|
||||
ARG PYTHON_VERSION=3.9
|
||||
ARG PYTHON_VERSION=3.10
|
||||
|
||||
###
|
||||
### Stage 0: generate requirements.txt
|
||||
###
|
||||
# We hardcode the use of Debian bookworm here because this could change upstream
|
||||
# and other Dockerfiles used for testing are expecting bookworm.
|
||||
FROM docker.io/library/python:${PYTHON_VERSION}-slim-bookworm
|
||||
# We hardcode the use of Debian trixie here because this could change upstream
|
||||
# and other Dockerfiles used for testing are expecting trixie.
|
||||
FROM docker.io/library/python:${PYTHON_VERSION}-slim-trixie
|
||||
|
||||
# Install Rust and other dependencies (stolen from normal Dockerfile)
|
||||
# install the OS build deps
|
||||
|
||||
+49
-18
@@ -6,7 +6,7 @@ import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Any, Dict, List, Mapping, MutableMapping, NoReturn, Optional
|
||||
from typing import Any, Mapping, MutableMapping, NoReturn
|
||||
|
||||
import jinja2
|
||||
|
||||
@@ -31,6 +31,25 @@ def flush_buffers() -> None:
|
||||
sys.stderr.flush()
|
||||
|
||||
|
||||
def strtobool(val: str) -> bool:
|
||||
"""Convert a string representation of truth to True or False
|
||||
|
||||
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
|
||||
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
|
||||
'val' is anything else.
|
||||
|
||||
This is lifted from distutils.util.strtobool, with the exception that it actually
|
||||
returns a bool, rather than an int.
|
||||
"""
|
||||
val = val.lower()
|
||||
if val in ("y", "yes", "t", "true", "on", "1"):
|
||||
return True
|
||||
elif val in ("n", "no", "f", "false", "off", "0"):
|
||||
return False
|
||||
else:
|
||||
raise ValueError("invalid truth value %r" % (val,))
|
||||
|
||||
|
||||
def convert(src: str, dst: str, environ: Mapping[str, object]) -> None:
|
||||
"""Generate a file from a template
|
||||
|
||||
@@ -50,7 +69,7 @@ def generate_config_from_template(
|
||||
config_dir: str,
|
||||
config_path: str,
|
||||
os_environ: Mapping[str, str],
|
||||
ownership: Optional[str],
|
||||
ownership: str | None,
|
||||
) -> None:
|
||||
"""Generate a homeserver.yaml from environment variables
|
||||
|
||||
@@ -69,7 +88,7 @@ def generate_config_from_template(
|
||||
)
|
||||
|
||||
# populate some params from data files (if they exist, else create new ones)
|
||||
environ: Dict[str, Any] = dict(os_environ)
|
||||
environ: dict[str, Any] = dict(os_environ)
|
||||
secrets = {
|
||||
"registration": "SYNAPSE_REGISTRATION_SHARED_SECRET",
|
||||
"macaroon": "SYNAPSE_MACAROON_SECRET_KEY",
|
||||
@@ -98,19 +117,16 @@ def generate_config_from_template(
|
||||
os.mkdir(config_dir)
|
||||
|
||||
# Convert SYNAPSE_NO_TLS to boolean if exists
|
||||
if "SYNAPSE_NO_TLS" in environ:
|
||||
tlsanswerstring = str.lower(environ["SYNAPSE_NO_TLS"])
|
||||
if tlsanswerstring in ("true", "on", "1", "yes"):
|
||||
environ["SYNAPSE_NO_TLS"] = True
|
||||
else:
|
||||
if tlsanswerstring in ("false", "off", "0", "no"):
|
||||
environ["SYNAPSE_NO_TLS"] = False
|
||||
else:
|
||||
error(
|
||||
'Environment variable "SYNAPSE_NO_TLS" found but value "'
|
||||
+ tlsanswerstring
|
||||
+ '" unrecognized; exiting.'
|
||||
)
|
||||
tlsanswerstring = environ.get("SYNAPSE_NO_TLS")
|
||||
if tlsanswerstring is not None:
|
||||
try:
|
||||
environ["SYNAPSE_NO_TLS"] = strtobool(tlsanswerstring)
|
||||
except ValueError:
|
||||
error(
|
||||
'Environment variable "SYNAPSE_NO_TLS" found but value "'
|
||||
+ tlsanswerstring
|
||||
+ '" unrecognized; exiting.'
|
||||
)
|
||||
|
||||
if "SYNAPSE_LOG_CONFIG" not in environ:
|
||||
environ["SYNAPSE_LOG_CONFIG"] = config_dir + "/log.config"
|
||||
@@ -147,7 +163,7 @@ def generate_config_from_template(
|
||||
subprocess.run(args, check=True)
|
||||
|
||||
|
||||
def run_generate_config(environ: Mapping[str, str], ownership: Optional[str]) -> None:
|
||||
def run_generate_config(environ: Mapping[str, str], ownership: str | None) -> None:
|
||||
"""Run synapse with a --generate-config param to generate a template config file
|
||||
|
||||
Args:
|
||||
@@ -164,6 +180,18 @@ def run_generate_config(environ: Mapping[str, str], ownership: Optional[str]) ->
|
||||
config_dir = environ.get("SYNAPSE_CONFIG_DIR", "/data")
|
||||
config_path = environ.get("SYNAPSE_CONFIG_PATH", config_dir + "/homeserver.yaml")
|
||||
data_dir = environ.get("SYNAPSE_DATA_DIR", "/data")
|
||||
enable_metrics_raw = environ.get("SYNAPSE_ENABLE_METRICS", "0")
|
||||
|
||||
enable_metrics = False
|
||||
if enable_metrics_raw is not None:
|
||||
try:
|
||||
enable_metrics = strtobool(enable_metrics_raw)
|
||||
except ValueError:
|
||||
error(
|
||||
'Environment variable "SYNAPSE_ENABLE_METRICS" found but value "'
|
||||
+ enable_metrics_raw
|
||||
+ '" unrecognized; exiting.'
|
||||
)
|
||||
|
||||
# create a suitable log config from our template
|
||||
log_config_file = "%s/%s.log.config" % (config_dir, server_name)
|
||||
@@ -190,6 +218,9 @@ def run_generate_config(environ: Mapping[str, str], ownership: Optional[str]) ->
|
||||
"--open-private-ports",
|
||||
]
|
||||
|
||||
if enable_metrics:
|
||||
args.append("--enable-metrics")
|
||||
|
||||
if ownership is not None:
|
||||
# make sure that synapse has perms to write to the data dir.
|
||||
log(f"Setting ownership on {data_dir} to {ownership}")
|
||||
@@ -200,7 +231,7 @@ def run_generate_config(environ: Mapping[str, str], ownership: Optional[str]) ->
|
||||
subprocess.run(args, check=True)
|
||||
|
||||
|
||||
def main(args: List[str], environ: MutableMapping[str, str]) -> None:
|
||||
def main(args: list[str], environ: MutableMapping[str, str]) -> None:
|
||||
mode = args[1] if len(args) > 1 else "run"
|
||||
|
||||
# if we were given an explicit user to switch to, do so
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Configuration for htmltest, which we run in CI to check that links aren't broken in the built documentation.
|
||||
# See all config options: https://github.com/wjdp/htmltest#wrench-configuration
|
||||
|
||||
# Don't check external links, as that requires network access and is slow.
|
||||
CheckExternal: false
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
# Setup
|
||||
- [Installation](setup/installation.md)
|
||||
- [Security](setup/security.md)
|
||||
- [Using Postgres](postgres.md)
|
||||
- [Configuring a Reverse Proxy](reverse_proxy.md)
|
||||
- [Configuring a Forward/Outbound Proxy](setup/forward_proxy.md)
|
||||
@@ -116,6 +117,8 @@
|
||||
- [The Auth Chain Difference Algorithm](auth_chain_difference_algorithm.md)
|
||||
- [Media Repository](media_repository.md)
|
||||
- [Room and User Statistics](room_and_user_statistics.md)
|
||||
- [Releasing]()
|
||||
- [Release Notes Review Checklist](development/internal_documentation/release_notes_review_checklist.md)
|
||||
- [Scripts]()
|
||||
|
||||
# Other
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Account validity API
|
||||
|
||||
**Note:** This API is disabled when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
**Note:** This API is disabled when Matrix Authentication Service integration is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
|
||||
This API allows a server administrator to manage the validity of an account. To
|
||||
use it, you must enable the account validity feature (under
|
||||
|
||||
@@ -88,6 +88,20 @@ is quarantined, Synapse will:
|
||||
- Quarantine any existing cached remote media.
|
||||
- Quarantine any future remote media.
|
||||
|
||||
## Downloading quarantined media
|
||||
|
||||
Normally, when media is quarantined, it will return a 404 error when downloaded.
|
||||
Admins can bypass this by adding `?admin_unsafely_bypass_quarantine=true`
|
||||
to the [normal download URL](https://spec.matrix.org/v1.16/client-server-api/#get_matrixclientv1mediadownloadservernamemediaid).
|
||||
|
||||
Bypassing the quarantine check is not recommended. Media is typically quarantined
|
||||
to prevent harmful content from being served to users, which includes admins. Only
|
||||
set the bypass parameter if you intentionally want to access potentially harmful
|
||||
content.
|
||||
|
||||
Non-admin users cannot bypass quarantine checks, even when specifying the above
|
||||
query parameter.
|
||||
|
||||
## Quarantining media by ID
|
||||
|
||||
This API quarantines a single piece of local or remote media.
|
||||
@@ -233,6 +247,42 @@ Response:
|
||||
{}
|
||||
```
|
||||
|
||||
## Listing quarantined media changes
|
||||
|
||||
When media is quarantined or unquarantined, a change record is created in the
|
||||
database. This API returns those change records in the order they were created.
|
||||
|
||||
**Note**: This API should be considered *best-effort* and expected to have missing or
|
||||
duplicate records. Currently, this only captures any media explicitly (un)quarantined by
|
||||
the media quarantine admin API, and the other cases are tracked by
|
||||
https://github.com/element-hq/synapse/issues/19672. Historical media uploaded before
|
||||
Synapse 1.152.0 is backfilled in a background update on a best-effort basis.
|
||||
|
||||
Each page has a maximum of 100 records. The first page has the oldest records,
|
||||
paginating forwards with each `next_batch` value.
|
||||
|
||||
Request:
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/media/quarantine_changes?from=2
|
||||
```
|
||||
|
||||
Where `from` is the `next_batch` value from a previous request. It is optional
|
||||
and defaults to the first page (the value `0`).
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"next_batch": 4,
|
||||
"changes": [
|
||||
{ "origin": "example.org", "media_id": "abcdefg12345...", "quarantined": true },
|
||||
{ "origin": "example.org", "media_id": "abcdefg12345...", "quarantined": false },
|
||||
{ "origin": "another.example.org", "media_id": "abcdefg12345...", "quarantined": true }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Delete local media
|
||||
This API deletes the *local* media from the disk of your own server.
|
||||
This includes any local thumbnails and copies of media downloaded from
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Shared-Secret Registration
|
||||
|
||||
**Note:** This API is disabled when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
**Note:** This API is disabled when Matrix Authentication Service integration is enabled.
|
||||
Use the [MAS Admin API](https://element-hq.github.io/matrix-authentication-service/topics/admin-api.html) or [the MAS CLI](https://element-hq.github.io/matrix-authentication-service/reference/cli/manage.html#manage-register-user) instead.
|
||||
|
||||
This API allows for the creation of users in an administrative and
|
||||
non-interactive way. This is generally used for bootstrapping a Synapse
|
||||
|
||||
+79
-1
@@ -308,6 +308,9 @@ The following fields are possible in the JSON response body:
|
||||
If the room does not define a type, the value will be `null`.
|
||||
* `forgotten` - Whether all local users have
|
||||
[forgotten](https://spec.matrix.org/latest/client-server-api/#leaving-rooms) the room.
|
||||
* `tombstoned` - Whether the room has been tombstoned (permanently closed).
|
||||
* `replacement_room` - The room ID of the new room that users should join instead, if this room was tombstoned. Will be
|
||||
`null` if the room has not been tombstoned, or if it was tombstoned without designating a successor room.
|
||||
|
||||
The API is:
|
||||
|
||||
@@ -337,7 +340,9 @@ A response body like the following is returned:
|
||||
"history_visibility": "shared",
|
||||
"state_events": 93534,
|
||||
"room_type": "m.space",
|
||||
"forgotten": false
|
||||
"forgotten": false,
|
||||
"tombstoned": false,
|
||||
"replacement_room": null
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1115,3 +1120,76 @@ Example response:
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Admin Space Hierarchy Endpoint
|
||||
|
||||
This API allows an admin to fetch the space/room hierarchy for a given space,
|
||||
returning details about that room and any children the room may have, paginating
|
||||
over the space tree in a depth-first manner to locate child rooms. This is
|
||||
functionally similar to the [CS Hierarchy](https://spec.matrix.org/v1.16/client-server-api/#get_matrixclientv1roomsroomidhierarchy) endpoint but does not check for
|
||||
room membership when returning room summaries.
|
||||
|
||||
The endpoint does not query other servers over federation about remote rooms
|
||||
that the server has not joined. This is a deliberate trade-off: while this
|
||||
means it will leave some holes in the hierarchy that we could otherwise
|
||||
sometimes fill in, it significantly improves the endpoint's response time and
|
||||
the admin endpoint is designed for managing rooms local to the homeserver
|
||||
anyway.
|
||||
|
||||
**Parameters**
|
||||
|
||||
The following query parameters are available:
|
||||
|
||||
* `from` - An optional pagination token, provided when there are more rooms to
|
||||
return than the limit.
|
||||
* `limit` - Maximum amount of rooms to return. Must be a non-negative integer,
|
||||
defaults to `50`.
|
||||
* `max_depth` - The maximum depth in the tree to explore, must be a non-negative
|
||||
integer. 0 would correspond to just the root room, 1 would include just the
|
||||
root room's children, etc. If not provided will recurse into the space tree without limit.
|
||||
|
||||
Request:
|
||||
|
||||
```http
|
||||
GET /_synapse/admin/v1/rooms/<room_id>/hierarchy
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"rooms":
|
||||
[
|
||||
{ "children_state": [
|
||||
{
|
||||
"content": {
|
||||
"via": ["local_test_server"]
|
||||
},
|
||||
"origin_server_ts": 1500,
|
||||
"sender": "@user:test",
|
||||
"state_key": "!QrMkkqBSwYRIFNFCso:test",
|
||||
"type": "m.space.child"
|
||||
}
|
||||
],
|
||||
"name": "space room",
|
||||
"guest_can_join": false,
|
||||
"join_rule": "public",
|
||||
"num_joined_members": 1,
|
||||
"room_id": "!sPOpNyMHbZAoAOsOFL:test",
|
||||
"room_type": "m.space",
|
||||
"world_readable": false
|
||||
},
|
||||
|
||||
{
|
||||
"children_state": [],
|
||||
"guest_can_join": true,
|
||||
"join_rule": "invite",
|
||||
"name": "nefarious",
|
||||
"num_joined_members": 1,
|
||||
"room_id": "!QrMkkqBSwYRIFNFCso:test",
|
||||
"topic": "being bad",
|
||||
"world_readable": false}
|
||||
],
|
||||
"next_batch": "KUYmRbeSpAoaAIgOKGgyaCEn"
|
||||
}
|
||||
```
|
||||
@@ -36,9 +36,10 @@ It returns a JSON body like the following:
|
||||
- "scheduled" - Task is scheduled but not active
|
||||
- "active" - Task is active and probably running, and if not will be run on next scheduler loop run
|
||||
- "complete" - Task has completed successfully
|
||||
- "cancelled" - Task has been cancelled
|
||||
- "failed" - Task is over and either returned a failed status, or had an exception
|
||||
|
||||
* `max_timestamp`: int - Is optional. Returns only the scheduled tasks with a timestamp inferior to the specified one.
|
||||
* `max_timestamp`: int - Is optional. Returns only the scheduled tasks with a timestamp (in milliseconds since the unix epoch) inferior to the specified one.
|
||||
|
||||
**Response**
|
||||
|
||||
|
||||
@@ -34,11 +34,11 @@ It returns a JSON body like the following:
|
||||
}
|
||||
],
|
||||
"avatar_url": "<avatar_url>", // can be null if not set
|
||||
"is_guest": 0,
|
||||
"admin": 0,
|
||||
"deactivated": 0,
|
||||
"is_guest": false,
|
||||
"admin": false,
|
||||
"deactivated": false,
|
||||
"erased": false,
|
||||
"shadow_banned": 0,
|
||||
"shadow_banned": false,
|
||||
"creation_ts": 1560432506,
|
||||
"last_seen_ts": 1732919539393,
|
||||
"appservice_id": null,
|
||||
@@ -183,24 +183,24 @@ A response body like the following is returned:
|
||||
"users": [
|
||||
{
|
||||
"name": "<user_id1>",
|
||||
"is_guest": 0,
|
||||
"admin": 0,
|
||||
"is_guest": false,
|
||||
"admin": false,
|
||||
"user_type": null,
|
||||
"deactivated": 0,
|
||||
"deactivated": false,
|
||||
"erased": false,
|
||||
"shadow_banned": 0,
|
||||
"shadow_banned": false,
|
||||
"displayname": "<User One>",
|
||||
"avatar_url": null,
|
||||
"creation_ts": 1560432668000,
|
||||
"locked": false
|
||||
}, {
|
||||
"name": "<user_id2>",
|
||||
"is_guest": 0,
|
||||
"admin": 1,
|
||||
"is_guest": false,
|
||||
"admin": true,
|
||||
"user_type": null,
|
||||
"deactivated": 0,
|
||||
"deactivated": false,
|
||||
"erased": false,
|
||||
"shadow_banned": 0,
|
||||
"shadow_banned": false,
|
||||
"displayname": "<User Two>",
|
||||
"avatar_url": "<avatar_url>",
|
||||
"creation_ts": 1561550621000,
|
||||
@@ -227,7 +227,8 @@ The following parameters should be set in the URL:
|
||||
- `name` - Is optional and filters to only return users with user ID localparts
|
||||
**or** displaynames that contain this value.
|
||||
- `guests` - string representing a bool - Is optional and if `false` will **exclude** guest users.
|
||||
Defaults to `true` to include guest users. This parameter is not supported when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
Defaults to `true` to include guest users. Setting this option to `true` is not supported when Matrix Authentication
|
||||
Service integration is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
- `admins` - Optional flag to filter admins. If `true`, only admins are queried. If `false`, admins are excluded from
|
||||
the query. When the flag is absent (the default), **both** admins and non-admins are included in the search results.
|
||||
- `deactivated` - string representing a bool - Is optional and if `true` will **include** deactivated users.
|
||||
@@ -403,6 +404,7 @@ is set to `true`:
|
||||
|
||||
- Remove the user's display name
|
||||
- Remove the user's avatar URL
|
||||
- Remove the user's custom profile fields
|
||||
- Mark the user as erased
|
||||
|
||||
The following actions are **NOT** performed. The list may be incomplete.
|
||||
@@ -443,7 +445,7 @@ To unsuspend a user, use the same endpoint with a body of:
|
||||
|
||||
## Reset password
|
||||
|
||||
**Note:** This API is disabled when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
**Note:** This API is disabled when Matrix Authentication Service integration is enabled. Use the [MAS Admin API](https://element-hq.github.io/matrix-authentication-service/topics/admin-api.html) or [the MAS CLI](https://element-hq.github.io/matrix-authentication-service/reference/cli/manage.html#manage-set-password) instead. An easy way to make use of this functionality is provided by [Element Admin](https://element.io/en/server-suite/admin) as part of [ESS](https://element.io/en/server-suite) Community and Pro.
|
||||
|
||||
Changes the password of another user. This will automatically log the user out of all their devices.
|
||||
|
||||
@@ -468,7 +470,7 @@ The parameter `logout_devices` is optional and defaults to `true`.
|
||||
|
||||
## Get whether a user is a server administrator or not
|
||||
|
||||
**Note:** This API is disabled when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
**Note:** This API is disabled when Matrix Authentication Service integration is enabled. Use the [MAS Admin API](https://element-hq.github.io/matrix-authentication-service/topics/admin-api.html) instead. An easy way to make use of this functionality is provided by [Element Admin](https://element.io/en/server-suite/admin) as part of [ESS](https://element.io/en/server-suite) Community and Pro.
|
||||
|
||||
The api is:
|
||||
|
||||
@@ -487,7 +489,7 @@ A response body like the following is returned:
|
||||
|
||||
## Change whether a user is a server administrator or not
|
||||
|
||||
**Note:** This API is disabled when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
**Note:** This API is disabled when Matrix Authentication Service integration is enabled. Use the [MAS Admin API](https://element-hq.github.io/matrix-authentication-service/topics/admin-api.html) or [the MAS CLI](https://element-hq.github.io/matrix-authentication-service/reference/cli/manage.html#manage-promote-admin) instead. An easy way to make use of this functionality is provided by [Element Admin](https://element.io/en/server-suite/admin) as part of [ESS](https://element.io/en/server-suite) Community and Pro.
|
||||
|
||||
Note that you cannot demote yourself.
|
||||
|
||||
@@ -505,6 +507,55 @@ with a body of:
|
||||
}
|
||||
```
|
||||
|
||||
## List room memberships of a user
|
||||
|
||||
Gets a list of room memberships for a specific `user_id`. This
|
||||
endpoint differs from
|
||||
[`GET /_synapse/admin/v1/users/<user_id>/joined_rooms`](#list-joined-rooms-of-a-user)
|
||||
in that it returns rooms with memberships other than "join".
|
||||
|
||||
The API is:
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/users/<user_id>/memberships
|
||||
```
|
||||
|
||||
A response body like the following is returned:
|
||||
|
||||
```json
|
||||
{
|
||||
"memberships": {
|
||||
"!DuGcnbhHGaSZQoNQR:matrix.org": "join",
|
||||
"!ZtSaPCawyWtxfWiIy:matrix.org": "leave",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
which is a list of room membership states for the given user. This endpoint can
|
||||
be used with both local and remote users, with the caveat that the homeserver will
|
||||
only be aware of the memberships for rooms that one of its local users has joined.
|
||||
|
||||
Remote user memberships may also be out of date if all local users have since left
|
||||
a room. The homeserver will thus no longer receive membership updates about it.
|
||||
|
||||
The list includes rooms that the user has since left; other membership states (knock,
|
||||
invite, etc.) are also possible.
|
||||
|
||||
Note that rooms will only disappear from this list if they are
|
||||
[purged](./rooms.md#delete-room-api) from the homeserver.
|
||||
|
||||
**Parameters**
|
||||
|
||||
The following parameters should be set in the URL:
|
||||
|
||||
- `user_id` - fully qualified: for example, `@user:server.com`.
|
||||
|
||||
**Response**
|
||||
|
||||
The following fields are returned in the JSON response body:
|
||||
|
||||
- `memberships` - A map of `room_id` (string) to `membership` state (string).
|
||||
|
||||
## List joined rooms of a user
|
||||
|
||||
Gets a list of all `room_id` that a specific `user_id` is joined to and is a member of (participating in).
|
||||
@@ -550,7 +601,7 @@ Fetches the number of invites sent by the provided user ID across all rooms
|
||||
after the given timestamp.
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/users/$user_id/sent_invite_count
|
||||
GET /_synapse/admin/v1/users/<user_id>/sent_invite_count
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
@@ -584,7 +635,7 @@ Fetches the number of rooms that the user joined after the given timestamp, even
|
||||
if they have subsequently left/been banned from those rooms.
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/users/$<user_id/cumulative_joined_room_count
|
||||
GET /_synapse/admin/v1/users/<user_id>/cumulative_joined_room_count
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
@@ -860,7 +911,7 @@ delete largest/smallest or newest/oldest files first.
|
||||
|
||||
## Login as a user
|
||||
|
||||
**Note:** This API is disabled when MSC3861 is enabled. [See #15582](https://github.com/matrix-org/synapse/pull/15582)
|
||||
**Note:** This API is disabled when Matrix Authentication Service integration is enabled. Use [Personal sessions](https://element-hq.github.io/matrix-authentication-service/topics/authorization.html#personal-sessions-personal-access-tokens) through the [MAS Admin API](https://element-hq.github.io/matrix-authentication-service/topics/admin-api.html) instead. An easy way to make use of this functionality is provided by [Element Admin](https://element.io/en/server-suite/admin) as part of [ESS](https://element.io/en/server-suite) Community and Pro.
|
||||
|
||||
Get an access token that can be used to authenticate as that user. Useful for
|
||||
when admins wish to do actions on behalf of a user.
|
||||
@@ -1389,7 +1440,7 @@ The request and response format is the same as the
|
||||
The API is:
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/auth_providers/$provider/users/$external_id
|
||||
GET /_synapse/admin/v1/auth_providers/<provider>/users/<external_id>
|
||||
```
|
||||
|
||||
When a user matched the given ID for the given provider, an HTTP code `200` with a response body like the following is returned:
|
||||
@@ -1428,7 +1479,7 @@ _Added in Synapse 1.68.0._
|
||||
The API is:
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/threepid/$medium/users/$address
|
||||
GET /_synapse/admin/v1/threepid/<medium>/users/<address>
|
||||
```
|
||||
|
||||
When a user matched the given address for the given medium, an HTTP code `200` with a response body like the following is returned:
|
||||
@@ -1462,24 +1513,28 @@ Returns a `404` HTTP status code if no user was found, with a response body like
|
||||
_Added in Synapse 1.72.0._
|
||||
|
||||
|
||||
## Redact all the events of a user
|
||||
## Redact events of a user
|
||||
|
||||
This endpoint allows an admin to redact the events of a given user. There are no restrictions on
|
||||
redactions for a local user. By default, we puppet the user who sent the message to redact it themselves.
|
||||
Redactions for non-local users are issued using the admin user, and will fail in rooms where the
|
||||
admin user is not admin/does not have the specified power level to issue redactions. An option
|
||||
is provided to override the default and allow the admin to issue the redactions in all cases.
|
||||
is provided to override the default and allow the admin to issue the redactions in all cases.
|
||||
There are optional parameters to filter for events that happened in the given time period.
|
||||
|
||||
The API is
|
||||
```
|
||||
POST /_synapse/admin/v1/user/$user_id/redact
|
||||
POST /_synapse/admin/v1/user/<user_id>/redact
|
||||
|
||||
{
|
||||
"rooms": ["!roomid1", "!roomid2"]
|
||||
"rooms": ["!roomid1", "!roomid2"],
|
||||
"after_ts": 1779564103728,
|
||||
"before_ts": 1779564103730
|
||||
}
|
||||
```
|
||||
If an empty list is provided as the key for `rooms`, all events in all the rooms the user is member of will be redacted,
|
||||
otherwise all the events in the rooms provided in the request will be redacted.
|
||||
If neither `after_ts` nor `before_ts` is provided, events will be redacted regardless of when they happened. If only one parameter is provided, all events occurring on or before/after given time will be redacted.
|
||||
|
||||
The API starts redaction process running, and returns immediately with a JSON body with
|
||||
a redact id which can be used to query the status of the redaction process:
|
||||
@@ -1507,7 +1562,9 @@ The following JSON body parameters are optional:
|
||||
- `limit` - a limit on the number of the user's events to search for ones that can be redacted (events are redacted newest to oldest) in each room, defaults to 1000 if not provided.
|
||||
- `use_admin` - If set to `true`, the admin user is used to issue the redactions, rather than puppeting the user. Useful
|
||||
when the admin is also the moderator of the rooms that require redactions. Note that the redactions will fail in rooms
|
||||
where the admin does not have the sufficient power level to issue the redactions.
|
||||
where the admin does not have the sufficient power level to issue the redactions.
|
||||
- `after_ts` - Redact only events that were sent at this time or after. Format: milliseconds timestamp. _Added in Synapse 1.157.0._
|
||||
- `before_ts` - Redact only events that were sent at this time or before. Format: milliseconds timestamp. _Added in Synapse 1.157.0._
|
||||
|
||||
_Added in Synapse 1.116.0._
|
||||
|
||||
@@ -1521,7 +1578,7 @@ or until Synapse is restarted (whichever happens first).
|
||||
The API is:
|
||||
|
||||
```
|
||||
GET /_synapse/admin/v1/user/redact_status/$redact_id
|
||||
GET /_synapse/admin/v1/user/redact_status/<redact_id>
|
||||
```
|
||||
|
||||
A response body like the following is returned:
|
||||
@@ -1549,5 +1606,3 @@ The following fields are returned in the JSON response body:
|
||||
the corresponding error that caused the redaction to fail
|
||||
|
||||
_Added in Synapse 1.116.0._
|
||||
|
||||
|
||||
+16
-10
@@ -21,8 +21,8 @@ people building from source should ensure they can fetch recent versions of Rust
|
||||
(e.g. by using [rustup](https://rustup.rs/)).
|
||||
|
||||
The oldest supported version of SQLite is the version
|
||||
[provided](https://packages.debian.org/bullseye/libsqlite3-0) by
|
||||
[Debian oldstable](https://wiki.debian.org/DebianOldStable).
|
||||
[provided](https://packages.debian.org/oldstable/libsqlite3-0) by
|
||||
[Debian oldstable](https://wiki.debian.org/DebianOldStable) or the oldest maintenance/security-supported [Ubuntu LTS](https://endoflife.date/ubuntu) (Ubuntu versions with only Expanded Security Maintenance are not included).
|
||||
|
||||
|
||||
### Context
|
||||
@@ -79,11 +79,17 @@ concerned about the criteria for selecting minimum versions. The only thing of c
|
||||
is making sure we're not making it unnecessarily difficult for downstream package
|
||||
maintainers. Generally, this just means avoiding the bleeding edge for a few months.
|
||||
|
||||
The situation for Rust dependencies is fundamentally different. For packagers, the
|
||||
concerns around Python dependency versions do not apply. The `cargo` tool handles
|
||||
downloading and building all libraries to satisfy dependencies, and these libraries are
|
||||
statically linked into the final binary. This means that from a packager's perspective,
|
||||
the Rust dependency versions are an internal build detail, not a runtime dependency to
|
||||
be managed on the target system. Consequently, we have even greater flexibility to
|
||||
upgrade Rust dependencies as needed for the project. Some distros (e.g. Fedora) do
|
||||
package Rust libraries, but this appears to be the outlier rather than the norm.
|
||||
The situation for Rust dependencies is typically different and
|
||||
the concerns around Python dependency versions typically do not apply.
|
||||
For example, for packagers of Debian, the packagers have the choice of either
|
||||
using a crate packaged in the distro, or vendoring crates in the source package for the
|
||||
application.
|
||||
|
||||
This freedom to vendor a dependency crate for a specific application consequently gives
|
||||
us even greater flexibility to upgrade Rust dependencies as needed for the project.
|
||||
|
||||
(This is in contrast with Python dependencies, which are generally
|
||||
installed system-wide by mainstream distributions' official packages.)
|
||||
|
||||
Some distros (e.g. Fedora) do not vendor Rust dependencies in their
|
||||
official application packages, but these cases appear to be less common.
|
||||
@@ -153,8 +153,14 @@ writing new pages, please
|
||||
to check that your contributions render correctly. The docs are written in
|
||||
[GitHub-Flavoured Markdown](https://guides.github.com/features/mastering-markdown/).
|
||||
|
||||
## Making changes to the Rust code
|
||||
|
||||
When changes are made to any Rust code then you must call either `poetry install`
|
||||
or `maturin develop` (if installed) to rebuild the Rust code. Using [`maturin`](https://github.com/PyO3/maturin)
|
||||
or `maturin develop` (if installed) to rebuild the Rust code.
|
||||
|
||||
You can use `poetry install -v` or `-vv` to get more info about build failures.
|
||||
|
||||
Using [`maturin`](https://github.com/PyO3/maturin)
|
||||
is quicker than `poetry install`, so is recommended when making frequent
|
||||
changes to the Rust code.
|
||||
|
||||
@@ -320,7 +326,7 @@ The following command will let you run the integration test with the most common
|
||||
configuration:
|
||||
|
||||
```sh
|
||||
$ docker run --rm -it -v /path/where/you/have/cloned/the/repository\:/src:ro -v /path/to/where/you/want/logs\:/logs matrixdotorg/sytest-synapse:bullseye
|
||||
$ docker run --rm -it -v /path/where/you/have/cloned/the/repository\:/src:ro -v /path/to/where/you/want/logs\:/logs matrixdotorg/sytest-synapse:bookworm
|
||||
```
|
||||
(Note that the paths must be full paths! You could also write `$(realpath relative/path)` if needed.)
|
||||
|
||||
@@ -334,46 +340,9 @@ For more details about other configurations, see the [Docker-specific documentat
|
||||
|
||||
## Run the integration tests ([Complement](https://github.com/matrix-org/complement)).
|
||||
|
||||
[Complement](https://github.com/matrix-org/complement) is a suite of black box tests that can be run on any homeserver implementation. It can also be thought of as end-to-end (e2e) tests.
|
||||
See our [Complement docs](https://github.com/element-hq/synapse/tree/develop/complement)
|
||||
for how to use the `./scripts-dev/complement.sh` test runner script.
|
||||
|
||||
It's often nice to develop on Synapse and write Complement tests at the same time.
|
||||
Here is how to run your local Synapse checkout against your local Complement checkout.
|
||||
|
||||
(checkout [`complement`](https://github.com/matrix-org/complement) alongside your `synapse` checkout)
|
||||
```sh
|
||||
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh
|
||||
```
|
||||
|
||||
To run a specific test file, you can pass the test name at the end of the command. The name passed comes from the naming structure in your Complement tests. If you're unsure of the name, you can do a full run and copy it from the test output:
|
||||
|
||||
```sh
|
||||
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestImportHistoricalMessages
|
||||
```
|
||||
|
||||
To run a specific test, you can specify the whole name structure:
|
||||
|
||||
```sh
|
||||
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestImportHistoricalMessages/parallel/Historical_events_resolve_in_the_correct_order
|
||||
```
|
||||
|
||||
The above will run a monolithic (single-process) Synapse with SQLite as the database. For other configurations, try:
|
||||
|
||||
- Passing `POSTGRES=1` as an environment variable to use the Postgres database instead.
|
||||
- Passing `WORKERS=1` as an environment variable to use a workerised setup instead. This option implies the use of Postgres.
|
||||
- If setting `WORKERS=1`, optionally set `WORKER_TYPES=` to declare which worker
|
||||
types you wish to test. A simple comma-delimited string containing the worker types
|
||||
defined from the `WORKERS_CONFIG` template in
|
||||
[here](https://github.com/element-hq/synapse/blob/develop/docker/configure_workers_and_start.py#L54).
|
||||
A safe example would be `WORKER_TYPES="federation_inbound, federation_sender, synchrotron"`.
|
||||
See the [worker documentation](../workers.md) for additional information on workers.
|
||||
- Passing `ASYNCIO_REACTOR=1` as an environment variable to use the Twisted asyncio reactor instead of the default one.
|
||||
- Passing `PODMAN=1` will use the [podman](https://podman.io/) container runtime, instead of docker.
|
||||
- Passing `UNIX_SOCKETS=1` will utilise Unix socket functionality for Synapse, Redis, and Postgres(when applicable).
|
||||
|
||||
To increase the log level for the tests, set `SYNAPSE_TEST_LOG_LEVEL`, e.g:
|
||||
```sh
|
||||
SYNAPSE_TEST_LOG_LEVEL=DEBUG COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestImportHistoricalMessages
|
||||
```
|
||||
|
||||
### Prettier formatting with `gotestfmt`
|
||||
|
||||
@@ -389,18 +358,6 @@ COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -json | gotestfmt -hide
|
||||
(Remove `-hide successful-tests` if you don't want to hide successful tests.)
|
||||
|
||||
|
||||
### Access database for homeserver after Complement test runs.
|
||||
|
||||
If you're curious what the database looks like after you run some tests, here are some steps to get you going in Synapse:
|
||||
|
||||
1. In your Complement test comment out `defer deployment.Destroy(t)` and replace with `defer time.Sleep(2 * time.Hour)` to keep the homeserver running after the tests complete
|
||||
1. Start the Complement tests
|
||||
1. Find the name of the container, `docker ps -f name=complement_` (this will filter for just the Compelement related Docker containers)
|
||||
1. Access the container replacing the name with what you found in the previous step: `docker exec -it complement_1_hs_with_application_service.hs1_2 /bin/bash`
|
||||
1. Install sqlite (database driver), `apt-get update && apt-get install -y sqlite3`
|
||||
1. Then run `sqlite3` and open the database `.open /conf/homeserver.db` (this db path comes from the Synapse homeserver.yaml)
|
||||
|
||||
|
||||
# 9. Submit your patch.
|
||||
|
||||
Once you're happy with your patch, it's time to prepare a Pull Request.
|
||||
|
||||
@@ -6,7 +6,7 @@ This is a quick cheat sheet for developers on how to use [`poetry`](https://pyth
|
||||
|
||||
See the [contributing guide](contributing_guide.md#4-install-the-dependencies).
|
||||
|
||||
Developers should use Poetry 1.3.2 or higher. If you encounter problems related
|
||||
Developers should use Poetry 2.2.0 or higher. If you encounter problems related
|
||||
to poetry, please [double-check your poetry version](#check-the-version-of-poetry-with-poetry---version).
|
||||
|
||||
# Background
|
||||
@@ -79,17 +79,17 @@ phonenumbers = [
|
||||
We can see this pinned version inside the docker image for that release:
|
||||
|
||||
```
|
||||
$ docker pull vectorim/synapse:v1.97.0
|
||||
$ docker pull matrixdotorg/synapse:latest
|
||||
...
|
||||
$ docker run --entrypoint pip vectorim/synapse:v1.97.0 show phonenumbers
|
||||
$ docker run --entrypoint pip matrixdotorg/synapse:latest show phonenumbers
|
||||
Name: phonenumbers
|
||||
Version: 8.12.44
|
||||
Version: 9.0.15
|
||||
Summary: Python version of Google's common library for parsing, formatting, storing and validating international phone numbers.
|
||||
Home-page: https://github.com/daviddrysdale/python-phonenumbers
|
||||
Author: David Drysdale
|
||||
Author-email: dmd@lurklurk.org
|
||||
License: Apache License 2.0
|
||||
Location: /usr/local/lib/python3.9/site-packages
|
||||
Location: /usr/local/lib/python3.12/site-packages
|
||||
Requires:
|
||||
Required-by: matrix-synapse
|
||||
```
|
||||
|
||||
@@ -32,6 +32,33 @@ expected and not an issue.
|
||||
It is not a requirement for experimental features to be behind a configuration flag,
|
||||
but one should be used if unsure.
|
||||
|
||||
New experimental configuration flags should be added under the `experimental`
|
||||
New experimental configuration flags should be added under the `experimental_features`
|
||||
configuration key (see the `synapse.config.experimental` file) and either explain
|
||||
(briefly) what is being enabled, or include the MSC number.
|
||||
The configuration flag should link to the tracking issue for the experimental feature (see below).
|
||||
|
||||
|
||||
## Tracking issues for experimental features
|
||||
|
||||
In the interest of having some documentation around experimental features, without
|
||||
polluting the stable documentation, all new experimental features should have a tracking issue with
|
||||
[the `T-ExperimentalFeature` label](https://github.com/element-hq/synapse/issues?q=sort%3Aupdated-desc+state%3Aopen+label%3A%22T-ExperimentalFeature%22),
|
||||
kept open as long as the experimental feature is present in Synapse.
|
||||
|
||||
The configuration option for the feature should have a comment linking to the tracking issue,
|
||||
for ease of discoverability.
|
||||
|
||||
As a guideline, the issue should contain:
|
||||
|
||||
- Context for why this experimental feature is in Synapse
|
||||
- This could well be a link to somewhere else, where this context is already available.
|
||||
- If applicable, why the feature is enabled by default. (Why do we need to enable it by default and why is it safe?)
|
||||
- If applicable, setup instructions for any non-standard components or configuration needed by the feature.
|
||||
(Ideally this will be moved to the configuration manual after stabilisation.)
|
||||
- Design decisions behind the Synapse implementation.
|
||||
(Ideally this will be moved to the developers' documentation after stabilisation.)
|
||||
- Any caveats around the current implementation of the feature, such as:
|
||||
- missing aspects
|
||||
- breakage or incompatibility that is expected if/when the feature is stabilised,
|
||||
or when the feature is turned on/off
|
||||
- Criteria for how we know whether we can remove the feature in the future.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Release notes review checklist
|
||||
|
||||
The Synapse release process includes a step to review the changelog before
|
||||
publishing it. The following is a list of common points to check for:
|
||||
|
||||
1. Check whether any similar entries that can be merged together (make sure to include all mentioned PRs at the end of the line, i.e. (#1234, #1235, ...)).
|
||||
2. Link any MSCXXXX lines to the Matrix Spec Change itself: <https://github.com/matrix-org/matrix-spec-proposals/pull/xxxx>.
|
||||
3. Wrap any class names, variable names, etc. in back-ticks, if needed.
|
||||
4. Hoist any relevant security, deprecation, etc. announcements to the top of this version's changelog for visibility. This includes any announcements in RCs for this release.
|
||||
5. Check the upgrade notes for any important announcements, and link to them from the changelog if warranted.
|
||||
6. Quickly skim and check that each entry is in the appropriate section.
|
||||
7. Entries under the Bugfixes section should ideally state what Synapse version the bug was introduced in. For example: "Fixed a bug introduced in v1.x.y" or if no version can be identified, "Fixed a long-standing bug ...".
|
||||
@@ -299,7 +299,7 @@ logcontext is not finished before the `async` processing completes.
|
||||
|
||||
**Bad**:
|
||||
```python
|
||||
cache: Optional[ObservableDeferred[None]] = None
|
||||
cache: ObservableDeferred[None] | None = None
|
||||
|
||||
async def do_something_else(
|
||||
to_resolve: Deferred[None]
|
||||
@@ -326,7 +326,7 @@ with LoggingContext("request-1"):
|
||||
|
||||
**Good**:
|
||||
```python
|
||||
cache: Optional[ObservableDeferred[None]] = None
|
||||
cache: ObservableDeferred[None] | None = None
|
||||
|
||||
async def do_something_else(
|
||||
to_resolve: Deferred[None]
|
||||
@@ -358,7 +358,7 @@ with LoggingContext("request-1"):
|
||||
|
||||
**OK**:
|
||||
```python
|
||||
cache: Optional[ObservableDeferred[None]] = None
|
||||
cache: ObservableDeferred[None] | None = None
|
||||
|
||||
async def do_something_else(
|
||||
to_resolve: Deferred[None]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## Streams
|
||||
# Streams
|
||||
|
||||
Synapse has a concept of "streams", which are roughly described in [`id_generators.py`](
|
||||
https://github.com/element-hq/synapse/blob/develop/synapse/storage/util/id_generators.py
|
||||
@@ -19,7 +19,7 @@ To that end, let's describe streams formally, paraphrasing from the docstring of
|
||||
https://github.com/element-hq/synapse/blob/a719b703d9bd0dade2565ddcad0e2f3a7a9d4c37/synapse/storage/util/id_generators.py#L96
|
||||
).
|
||||
|
||||
### Definition
|
||||
## Definition
|
||||
|
||||
A stream is an append-only log `T1, T2, ..., Tn, ...` of facts[^1] which grows over time.
|
||||
Only "writers" can add facts to a stream, and there may be multiple writers.
|
||||
@@ -47,7 +47,7 @@ But unhappy cases (e.g. transaction rollback due to an error) also count as comp
|
||||
Once completed, the rows written with that stream ID are fixed, and no new rows
|
||||
will be inserted with that ID.
|
||||
|
||||
### Current stream ID
|
||||
## Current stream ID
|
||||
|
||||
For any given stream reader (including writers themselves), we may define a per-writer current stream ID:
|
||||
|
||||
@@ -93,7 +93,7 @@ Consider a single-writer stream which is initially at ID 1.
|
||||
| Complete 6 | 6 | |
|
||||
|
||||
|
||||
### Multi-writer streams
|
||||
## Multi-writer streams
|
||||
|
||||
There are two ways to view a multi-writer stream.
|
||||
|
||||
@@ -115,7 +115,7 @@ The facts this stream holds are instructions to "you should now invalidate these
|
||||
We only ever treat this as a multiple single-writer streams as there is no important ordering between cache invalidations.
|
||||
(Invalidations are self-contained facts; and the invalidations commute/are idempotent).
|
||||
|
||||
### Writing to streams
|
||||
## Writing to streams
|
||||
|
||||
Writers need to track:
|
||||
- track their current position (i.e. its own per-writer stream ID).
|
||||
@@ -133,7 +133,7 @@ To complete a fact, first remove it from your map of facts currently awaiting co
|
||||
Then, if no earlier fact is awaiting completion, the writer can advance its current position in that stream.
|
||||
Upon doing so it should emit an `RDATA` message[^3], once for every fact between the old and the new stream ID.
|
||||
|
||||
### Subscribing to streams
|
||||
## Subscribing to streams
|
||||
|
||||
Readers need to track the current position of every writer.
|
||||
|
||||
@@ -146,10 +146,53 @@ The `RDATA` itself is not a self-contained representation of the fact;
|
||||
readers will have to query the stream tables for the full details.
|
||||
Readers must also advance their record of the writer's current position for that stream.
|
||||
|
||||
# Summary
|
||||
## Summary
|
||||
|
||||
In a nutshell: we have an append-only log with a "buffer/scratchpad" at the end where we have to wait for the sequence to be linear and contiguous.
|
||||
|
||||
---
|
||||
|
||||
## Cheatsheet for creating a new stream
|
||||
|
||||
These rough notes and links may help you to create a new stream and add all the
|
||||
necessary registration and event handling.
|
||||
|
||||
**Create your stream:**
|
||||
- Create a Postgres-specific database delta file to [add a new `SEQUENCE`](https://github.com/element-hq/synapse/blob/35b55e962aa0bed3b2da5a3c12e3783ddf7604ca/synapse/storage/schema/main/delta/93/01_sticky_events_seq.sql.postgres#L14-L18) (this will be referenced by the `MultiWriterIdGenerator` below).
|
||||
- Update `synapse/_scripts/synapse_port_db.py` so it knows about your new `SEQUENCE`: [add a new `_setup_sequence(...)`](https://github.com/element-hq/synapse/blob/35b55e962aa0bed3b2da5a3c12e3783ddf7604ca/synapse/_scripts/synapse_port_db.py#L883C24-L888)
|
||||
- [create a stream class and stream row class](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/replication/tcp/streams/_base.py#L728)
|
||||
- will need an [ID generator](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/storage/databases/main/thread_subscriptions.py#L75)
|
||||
- may need [writer configuration](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/config/workers.py#L177), if there isn't already an obvious source of configuration for which workers should be designated as writers to your new stream.
|
||||
- if adding new writer configuration, add Docker-worker configuration, which lets us configure the writer worker in Complement tests: [[1]](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/docker/configure_workers_and_start.py#L331), [[2]](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/docker/configure_workers_and_start.py#L440)
|
||||
- most of the time, you will likely introduce a new datastore class for the concept represented by the new stream, unless there is already an obvious datastore that covers it.
|
||||
- consider whether it may make sense to introduce a handler
|
||||
|
||||
**Register your stream in:**
|
||||
- [`STREAMS_MAP`](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/replication/tcp/streams/__init__.py#L71)
|
||||
|
||||
**Advance your stream in:**
|
||||
- [`process_replication_position` of your appropriate datastore](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/storage/databases/main/thread_subscriptions.py#L111)
|
||||
- don't forget the super call
|
||||
|
||||
**If you're going to do any caching that needs invalidation from new rows:**
|
||||
- add invalidations to [`process_replication_rows` of your appropriate datastore](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/storage/databases/main/thread_subscriptions.py#L91)
|
||||
- don't forget the super call
|
||||
- add local-only [invalidations to your writer transactions](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/storage/databases/main/thread_subscriptions.py#L201)
|
||||
|
||||
**Update docs:**
|
||||
- Update the [*Stream
|
||||
writers*](https://github.com/element-hq/synapse/blob/develop/docs/workers.md#stream-writers)
|
||||
section in the worker docs with a new section for the stream
|
||||
- If this stream can only be handled by specific workers, add a new section to the
|
||||
[upgrade notes](https://github.com/element-hq/synapse/blob/develop/docs/upgrade.md).
|
||||
|
||||
**For streams to be used in sync:**
|
||||
- add a new field to [`StreamToken`](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/types/__init__.py#L1003)
|
||||
- add a new [`StreamKeyType`](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/types/__init__.py#L999)
|
||||
- add appropriate wake-up rules
|
||||
- in [`on_rdata`](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/replication/tcp/client.py#L260)
|
||||
- locally on the same worker when completing a write, [e.g. in your handler](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/handlers/thread_subscriptions.py#L139)
|
||||
- add the stream in [`bound_future_token`](https://github.com/element-hq/synapse/blob/4367fb2d078c52959aeca0fe6874539c53e8360d/synapse/streams/events.py#L127)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-173
@@ -123,193 +123,21 @@ Example Prometheus target for Synapse with workers:
|
||||
static_configs:
|
||||
- targets: ["my.server.here:port"]
|
||||
labels:
|
||||
instance: "my.server"
|
||||
job: "master"
|
||||
index: 1
|
||||
- targets: ["my.workerserver.here:port"]
|
||||
labels:
|
||||
instance: "my.server"
|
||||
job: "generic_worker"
|
||||
index: 1
|
||||
- targets: ["my.workerserver.here:port"]
|
||||
labels:
|
||||
instance: "my.server"
|
||||
job: "generic_worker"
|
||||
index: 2
|
||||
- targets: ["my.workerserver.here:port"]
|
||||
labels:
|
||||
instance: "my.server"
|
||||
job: "media_repository"
|
||||
index: 1
|
||||
```
|
||||
|
||||
Labels (`instance`, `job`, `index`) can be defined as anything.
|
||||
Labels (`job`, `index`) can be defined as anything.
|
||||
The labels are used to group graphs in grafana.
|
||||
|
||||
## Renaming of metrics & deprecation of old names in 1.2
|
||||
|
||||
Synapse 1.2 updates the Prometheus metrics to match the naming
|
||||
convention of the upstream `prometheus_client`. The old names are
|
||||
considered deprecated and will be removed in a future version of
|
||||
Synapse.
|
||||
**The old names will be disabled by default in Synapse v1.71.0 and removed
|
||||
altogether in Synapse v1.73.0.**
|
||||
|
||||
| New Name | Old Name |
|
||||
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
||||
| python_gc_objects_collected_total | python_gc_objects_collected |
|
||||
| python_gc_objects_uncollectable_total | python_gc_objects_uncollectable |
|
||||
| python_gc_collections_total | python_gc_collections |
|
||||
| process_cpu_seconds_total | process_cpu_seconds |
|
||||
| synapse_federation_client_sent_transactions_total | synapse_federation_client_sent_transactions |
|
||||
| synapse_federation_client_events_processed_total | synapse_federation_client_events_processed |
|
||||
| synapse_event_processing_loop_count_total | synapse_event_processing_loop_count |
|
||||
| synapse_event_processing_loop_room_count_total | synapse_event_processing_loop_room_count |
|
||||
| synapse_util_caches_cache_hits | synapse_util_caches_cache:hits |
|
||||
| synapse_util_caches_cache_size | synapse_util_caches_cache:size |
|
||||
| synapse_util_caches_cache_evicted_size | synapse_util_caches_cache:evicted_size |
|
||||
| synapse_util_caches_cache | synapse_util_caches_cache:total |
|
||||
| synapse_util_caches_response_cache_size | synapse_util_caches_response_cache:size |
|
||||
| synapse_util_caches_response_cache_hits | synapse_util_caches_response_cache:hits |
|
||||
| synapse_util_caches_response_cache_evicted_size | synapse_util_caches_response_cache:evicted_size |
|
||||
| synapse_util_metrics_block_count_total | synapse_util_metrics_block_count |
|
||||
| synapse_util_metrics_block_time_seconds_total | synapse_util_metrics_block_time_seconds |
|
||||
| synapse_util_metrics_block_ru_utime_seconds_total | synapse_util_metrics_block_ru_utime_seconds |
|
||||
| synapse_util_metrics_block_ru_stime_seconds_total | synapse_util_metrics_block_ru_stime_seconds |
|
||||
| synapse_util_metrics_block_db_txn_count_total | synapse_util_metrics_block_db_txn_count |
|
||||
| synapse_util_metrics_block_db_txn_duration_seconds_total | synapse_util_metrics_block_db_txn_duration_seconds |
|
||||
| synapse_util_metrics_block_db_sched_duration_seconds_total | synapse_util_metrics_block_db_sched_duration_seconds |
|
||||
| synapse_background_process_start_count_total | synapse_background_process_start_count |
|
||||
| synapse_background_process_ru_utime_seconds_total | synapse_background_process_ru_utime_seconds |
|
||||
| synapse_background_process_ru_stime_seconds_total | synapse_background_process_ru_stime_seconds |
|
||||
| synapse_background_process_db_txn_count_total | synapse_background_process_db_txn_count |
|
||||
| synapse_background_process_db_txn_duration_seconds_total | synapse_background_process_db_txn_duration_seconds |
|
||||
| synapse_background_process_db_sched_duration_seconds_total | synapse_background_process_db_sched_duration_seconds |
|
||||
| synapse_storage_events_persisted_events_total | synapse_storage_events_persisted_events |
|
||||
| synapse_storage_events_persisted_events_sep_total | synapse_storage_events_persisted_events_sep |
|
||||
| synapse_storage_events_state_delta_total | synapse_storage_events_state_delta |
|
||||
| synapse_storage_events_state_delta_single_event_total | synapse_storage_events_state_delta_single_event |
|
||||
| synapse_storage_events_state_delta_reuse_delta_total | synapse_storage_events_state_delta_reuse_delta |
|
||||
| synapse_federation_server_received_pdus_total | synapse_federation_server_received_pdus |
|
||||
| synapse_federation_server_received_edus_total | synapse_federation_server_received_edus |
|
||||
| synapse_handler_presence_notified_presence_total | synapse_handler_presence_notified_presence |
|
||||
| synapse_handler_presence_federation_presence_out_total | synapse_handler_presence_federation_presence_out |
|
||||
| synapse_handler_presence_presence_updates_total | synapse_handler_presence_presence_updates |
|
||||
| synapse_handler_presence_timers_fired_total | synapse_handler_presence_timers_fired |
|
||||
| synapse_handler_presence_federation_presence_total | synapse_handler_presence_federation_presence |
|
||||
| synapse_handler_presence_bump_active_time_total | synapse_handler_presence_bump_active_time |
|
||||
| synapse_federation_client_sent_edus_total | synapse_federation_client_sent_edus |
|
||||
| synapse_federation_client_sent_pdu_destinations_count_total | synapse_federation_client_sent_pdu_destinations:count |
|
||||
| synapse_federation_client_sent_pdu_destinations_total | synapse_federation_client_sent_pdu_destinations:total |
|
||||
| synapse_handlers_appservice_events_processed_total | synapse_handlers_appservice_events_processed |
|
||||
| synapse_notifier_notified_events_total | synapse_notifier_notified_events |
|
||||
| synapse_push_bulk_push_rule_evaluator_push_rules_invalidation_counter_total | synapse_push_bulk_push_rule_evaluator_push_rules_invalidation_counter |
|
||||
| synapse_push_bulk_push_rule_evaluator_push_rules_state_size_counter_total | synapse_push_bulk_push_rule_evaluator_push_rules_state_size_counter |
|
||||
| synapse_http_httppusher_http_pushes_processed_total | synapse_http_httppusher_http_pushes_processed |
|
||||
| synapse_http_httppusher_http_pushes_failed_total | synapse_http_httppusher_http_pushes_failed |
|
||||
| synapse_http_httppusher_badge_updates_processed_total | synapse_http_httppusher_badge_updates_processed |
|
||||
| synapse_http_httppusher_badge_updates_failed_total | synapse_http_httppusher_badge_updates_failed |
|
||||
| synapse_admin_mau_current | synapse_admin_mau:current |
|
||||
| synapse_admin_mau_max | synapse_admin_mau:max |
|
||||
| synapse_admin_mau_registered_reserved_users | synapse_admin_mau:registered_reserved_users |
|
||||
|
||||
Removal of deprecated metrics & time based counters becoming histograms in 0.31.0
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
The duplicated metrics deprecated in Synapse 0.27.0 have been removed.
|
||||
|
||||
All time duration-based metrics have been changed to be seconds. This
|
||||
affects:
|
||||
|
||||
| msec -> sec metrics |
|
||||
| -------------------------------------- |
|
||||
| python_gc_time |
|
||||
| python_twisted_reactor_tick_time |
|
||||
| synapse_storage_query_time |
|
||||
| synapse_storage_schedule_time |
|
||||
| synapse_storage_transaction_time |
|
||||
|
||||
Several metrics have been changed to be histograms, which sort entries
|
||||
into buckets and allow better analysis. The following metrics are now
|
||||
histograms:
|
||||
|
||||
| Altered metrics |
|
||||
| ------------------------------------------------ |
|
||||
| python_gc_time |
|
||||
| python_twisted_reactor_pending_calls |
|
||||
| python_twisted_reactor_tick_time |
|
||||
| synapse_http_server_response_time_seconds |
|
||||
| synapse_storage_query_time |
|
||||
| synapse_storage_schedule_time |
|
||||
| synapse_storage_transaction_time |
|
||||
|
||||
Block and response metrics renamed for 0.27.0
|
||||
---------------------------------------------
|
||||
|
||||
Synapse 0.27.0 begins the process of rationalising the duplicate
|
||||
`*:count` metrics reported for the resource tracking for code blocks and
|
||||
HTTP requests.
|
||||
|
||||
At the same time, the corresponding `*:total` metrics are being renamed,
|
||||
as the `:total` suffix no longer makes sense in the absence of a
|
||||
corresponding `:count` metric.
|
||||
|
||||
To enable a graceful migration path, this release just adds new names
|
||||
for the metrics being renamed. A future release will remove the old
|
||||
ones.
|
||||
|
||||
The following table shows the new metrics, and the old metrics which
|
||||
they are replacing.
|
||||
|
||||
| New name | Old name |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| synapse_util_metrics_block_count | synapse_util_metrics_block_timer:count |
|
||||
| synapse_util_metrics_block_count | synapse_util_metrics_block_ru_utime:count |
|
||||
| synapse_util_metrics_block_count | synapse_util_metrics_block_ru_stime:count |
|
||||
| synapse_util_metrics_block_count | synapse_util_metrics_block_db_txn_count:count |
|
||||
| synapse_util_metrics_block_count | synapse_util_metrics_block_db_txn_duration:count |
|
||||
| synapse_util_metrics_block_time_seconds | synapse_util_metrics_block_timer:total |
|
||||
| synapse_util_metrics_block_ru_utime_seconds | synapse_util_metrics_block_ru_utime:total |
|
||||
| synapse_util_metrics_block_ru_stime_seconds | synapse_util_metrics_block_ru_stime:total |
|
||||
| synapse_util_metrics_block_db_txn_count | synapse_util_metrics_block_db_txn_count:total |
|
||||
| synapse_util_metrics_block_db_txn_duration_seconds | synapse_util_metrics_block_db_txn_duration:total |
|
||||
| synapse_http_server_response_count | synapse_http_server_requests |
|
||||
| synapse_http_server_response_count | synapse_http_server_response_time:count |
|
||||
| synapse_http_server_response_count | synapse_http_server_response_ru_utime:count |
|
||||
| synapse_http_server_response_count | synapse_http_server_response_ru_stime:count |
|
||||
| synapse_http_server_response_count | synapse_http_server_response_db_txn_count:count |
|
||||
| synapse_http_server_response_count | synapse_http_server_response_db_txn_duration:count |
|
||||
| synapse_http_server_response_time_seconds | synapse_http_server_response_time:total |
|
||||
| synapse_http_server_response_ru_utime_seconds | synapse_http_server_response_ru_utime:total |
|
||||
| synapse_http_server_response_ru_stime_seconds | synapse_http_server_response_ru_stime:total |
|
||||
| synapse_http_server_response_db_txn_count | synapse_http_server_response_db_txn_count:total |
|
||||
| synapse_http_server_response_db_txn_duration_seconds | synapse_http_server_response_db_txn_duration:total |
|
||||
|
||||
Standard Metric Names
|
||||
---------------------
|
||||
|
||||
As of synapse version 0.18.2, the format of the process-wide metrics has
|
||||
been changed to fit prometheus standard naming conventions. Additionally
|
||||
the units have been changed to seconds, from milliseconds.
|
||||
|
||||
| New name | Old name |
|
||||
| ---------------------------------------- | --------------------------------- |
|
||||
| process_cpu_user_seconds_total | process_resource_utime / 1000 |
|
||||
| process_cpu_system_seconds_total | process_resource_stime / 1000 |
|
||||
| process_open_fds (no \'type\' label) | process_fds |
|
||||
|
||||
The python-specific counts of garbage collector performance have been
|
||||
renamed.
|
||||
|
||||
| New name | Old name |
|
||||
| -------------------------------- | -------------------------- |
|
||||
| python_gc_time | reactor_gc_time |
|
||||
| python_gc_unreachable_total | reactor_gc_unreachable |
|
||||
| python_gc_counts | reactor_gc_counts |
|
||||
|
||||
The twisted-specific reactor metrics have been renamed.
|
||||
|
||||
| New name | Old name |
|
||||
| -------------------------------------- | ----------------------- |
|
||||
| python_twisted_reactor_pending_calls | reactor_pending_calls |
|
||||
| python_twisted_reactor_tick_time | reactor_tick_time |
|
||||
@@ -15,7 +15,7 @@ _First introduced in Synapse v1.57.0_
|
||||
```python
|
||||
async def on_account_data_updated(
|
||||
user_id: str,
|
||||
room_id: Optional[str],
|
||||
room_id: str | None,
|
||||
account_data_type: str,
|
||||
content: "synapse.module_api.JsonDict",
|
||||
) -> None:
|
||||
@@ -82,7 +82,7 @@ class CustomAccountDataModule:
|
||||
async def log_new_account_data(
|
||||
self,
|
||||
user_id: str,
|
||||
room_id: Optional[str],
|
||||
room_id: str | None,
|
||||
account_data_type: str,
|
||||
content: JsonDict,
|
||||
) -> None:
|
||||
|
||||
@@ -12,7 +12,7 @@ The available account validity callbacks are:
|
||||
_First introduced in Synapse v1.39.0_
|
||||
|
||||
```python
|
||||
async def is_user_expired(user: str) -> Optional[bool]
|
||||
async def is_user_expired(user: str) -> bool | None
|
||||
```
|
||||
|
||||
Called when processing any authenticated request (except for logout requests). The module
|
||||
|
||||
@@ -11,7 +11,7 @@ The available media repository callbacks are:
|
||||
_First introduced in Synapse v1.132.0_
|
||||
|
||||
```python
|
||||
async def get_media_config_for_user(user_id: str) -> Optional[JsonDict]
|
||||
async def get_media_config_for_user(user_id: str) -> JsonDict | None
|
||||
```
|
||||
|
||||
**<span style="color:red">
|
||||
@@ -70,7 +70,7 @@ implementations of this callback.
|
||||
_First introduced in Synapse v1.139.0_
|
||||
|
||||
```python
|
||||
async def get_media_upload_limits_for_user(user_id: str, size: int) -> Optional[List[synapse.module_api.MediaUploadLimit]]
|
||||
async def get_media_upload_limits_for_user(user_id: str, size: int) -> list[synapse.module_api.MediaUploadLimit] | None
|
||||
```
|
||||
|
||||
**<span style="color:red">
|
||||
|
||||
Loaded 100 of 939 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user