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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions jenkins/pipelines/QE/es/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ pipeline {
string(name: 'ES_VERSION', defaultValue: '1.0.1', description: 'Edge Server version')
choice(name: 'TEST_DIR', choices: ['both','QE', 'dev_e2e'], description: 'Edge Server test directory: tests/QE/edge_server, tests/dev_e2e/edge_server, or both')
string(name: 'TEST_NAME', defaultValue: '.', description: '"." runs all tests in TEST_DIR; anything else is passed to pytest -k (not allowed with TEST_DIR=both)')
string(name: 'TOPOLOGY_NAME', defaultValue: 'es_sgw_topology.json', description: 'Topology file name')
string(name: 'TOPOLOGY_NAME', defaultValue: 'es_sgw_topology.json', description: 'Topology file name. 3es_1sgw_1js_topology.json also runs a CBL-JS test server on the Jenkins agent (localhost), and needs CBL_VERSION.')
string(name: 'CBL_VERSION', defaultValue: '', description: 'CBL-JS version-build for a topology with a JS test server (e.g. 1.1.0-25). Leave empty for topologies without test servers.')
booleanParam(name: 'RUN_PREBUILD', defaultValue: true, description: 'Prebuild the JS test server for CBL_VERSION. Uncheck to reuse existing artifacts.')
string(name: 'SGW_VERSION', defaultValue: '', description: 'Sync Gateway version (leave empty to skip SGW/CBS provisioning)')
string(name: 'CBS_VERSION', defaultValue: '', description: 'Couchbase Server version (leave empty to skip SGW/CBS provisioning)')
string(name: 'TS_DATASET_VERSION', defaultValue: '4.0', description: 'The version of the dataset to use on the test servers')
booleanParam(name: 'JS_REPLICATION_TESTS_ONLY', defaultValue: false, description: 'Run only the tests that replicate with the CBL-JS test server (those marked min_test_servers, all in tests/QE/edge_server). Needs a topology with a JS test server. TEST_NAME still narrows them with -k; TEST_DIR is ignored.')
}
options {
ansiColor('xterm')
Expand All @@ -19,9 +22,31 @@ pipeline {
script {
if (params.ES_VERSION == '') { error "ES_VERSION is required" }
if (params.TEST_NAME == '') { error "TEST_NAME is required" }
if (params.TEST_DIR == 'both' && params.TEST_NAME != '.') { error "TEST_NAME must be '.' when TEST_DIR is 'both'" }
if (params.TEST_DIR == 'both' && params.TEST_NAME != '.' && !params.JS_REPLICATION_TESTS_ONLY) { error "TEST_NAME must be '.' when TEST_DIR is 'both'" }
if (params.TOPOLOGY_NAME.contains('js_topology') && !params.CBL_VERSION) { error "CBL_VERSION is required for ${params.TOPOLOGY_NAME}" }
if (params.CBL_VERSION && !(params.CBL_VERSION ==~ /\d+\.\d+\.\d+-\d+/)) { error "CBL_VERSION must be <version>-<build>, e.g. 1.1.0-25" }
if (params.JS_REPLICATION_TESTS_ONLY && !params.TOPOLOGY_NAME.contains('js_topology')) {
error "JS_REPLICATION_TESTS_ONLY needs a topology with a JS test server (e.g. 3es_1sgw_1js_topology.json); ${params.TOPOLOGY_NAME} has none, so every selected test would be skipped"
}
def scope = params.JS_REPLICATION_TESTS_ONLY ? "QE (JS replication only)" : params.TEST_DIR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why there is this focus on putting in so many switches to make a "Javascript only" run. This likely can be done in a platform agnostic way.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my previous comment, it is to make Javascript RC validation easier. It wouldn't make sense to have a separate pipeline just for these tests.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I agree with that second part, it's just button overload here. Are you suggesting that this is just a way to run a subset of tests (that are part of a bigger pipeline) on Jenkins? Does it get reported to greenboard? Should it? If not, then why is it not merely a local option rather than a button on Jenkins? Jenkins shouldn't be used for debugging tests by running a subset, that should be done locally on your machine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a release validation step- http://jenkins.mobiledev.couchbase.com/view/QE/job/qe-edge-server-pipeline/62 was used to certify the CBL JS 1.0.3 RC. However, I don't think it gets reported to greenboard, that part would be more complex since greenboard does not report results if a subset of tests are run if I remember correctly. Do you have any recommendation for that

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think it's ok for now.

currentBuild.displayName = "ES:${params.ES_VERSION} (#${currentBuild.number})"
currentBuild.description = "${params.TEST_DIR}: ${params.TEST_NAME} | SGW: ${params.SGW_VERSION ?: 'none'} | CBS: ${params.CBS_VERSION ?: 'none'}"
currentBuild.description = "${scope}: ${params.TEST_NAME} | SGW: ${params.SGW_VERSION ?: 'none'} | CBS: ${params.CBS_VERSION ?: 'none'} | CBL-JS: ${params.CBL_VERSION ?: 'none'}"
}
}
}
stage('Prebuild JS Test Server') {
when { beforeAgent true; expression { params.CBL_VERSION && params.RUN_PREBUILD } }
steps {
script {
def (cblVersion, cblBuild) = params.CBL_VERSION.tokenize('-')
build job: 'prebuild-test-server',
parameters: [
string(name: 'TS_PLATFORM', value: 'js'),
string(name: 'CBL_VERSION', value: cblVersion),
string(name: 'CBL_BUILD', value: cblBuild)
],
wait: true,
propagate: true
}
}
}
Expand All @@ -37,7 +62,7 @@ pipeline {
// Unlock keychain:
sh 'security unlock-keychain -p ${KEYCHAIN_PASSWORD} ~/Library/Keychains/login.keychain-db'
echo "=== Run Edge server Tests"
timeout(time: 60, unit: 'MINUTES') {
timeout(time: 90, unit: 'MINUTES') {
sh """
jenkins/pipelines/QE/es/test.sh \
"${params.ES_VERSION}" \
Expand All @@ -46,7 +71,9 @@ pipeline {
"${params.SGW_VERSION}" \
"${params.CBS_VERSION}" \
"${params.TS_DATASET_VERSION}" \
"${params.TEST_DIR}"
"${params.TEST_DIR}" \
"${params.CBL_VERSION}" \
"${params.JS_REPLICATION_TESTS_ONLY}"
"""
}
echo "=== Edge server Tests Complete"
Expand All @@ -61,7 +88,7 @@ pipeline {
timeout(time: 5, unit: 'MINUTES') {
sh "jenkins/pipelines/QE/es/teardown.sh"
}
archiveArtifacts artifacts: 'tests/QE/es/**/*', fingerprint: true, allowEmptyArchive: true
archiveArtifacts artifacts: 'tests/QE/edge_server/es/**, tests/dev_e2e/edge_server/es/**', fingerprint: true, allowEmptyArchive: true
echo "=== Edge server Test Teardown Complete"
}
}
Expand Down
14 changes: 13 additions & 1 deletion jenkins/pipelines/QE/es/setup_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ def generate_topology(
topology_out: Path,
sgw_version: str | None = None,
cbs_version: str | None = None,
cbl_version: str | None = None,
tag: str = "es",
) -> None:
"""
Generate a topology JSON without injecting implicit CBS/SGW defaults.
Generate a topology JSON without injecting implicit CBS/SGW defaults. A topology with test
servers (such as the localhost JS test server) needs `cbl_version`, the CBL version to run.
"""

with topology_in.open() as f:
Expand All @@ -49,6 +51,12 @@ def generate_topology(
if cbs:
for cb in cbs:
cb["version"] = cbs_version
test_servers = topology.get("test_servers")
if test_servers:
if not cbl_version:
raise click.UsageError(f"{topology_in.name} has test servers, so --cbl-version is required")
for ts in test_servers:
ts["cbl_version"] = cbl_version

topology_out.parent.mkdir(parents=True, exist_ok=True)
with topology_out.open("w") as f:
Expand All @@ -66,12 +74,14 @@ def generate_topology(
)
@click.option("--sgw-version", default=None, help="Provision Sync Gateway (omit for latest release)")
@click.option("--cbs-version", default=None, help="Provision Couchbase Server (omit for latest release)")
@click.option("--cbl-version", default=None, help="CBL version-build for the topology's test servers, e.g. 1.1.0-25")
@click.option("--config-file", default="config.json", help="Backend config file")
def main(
es_version: str,
topology_file: Path,
sgw_version: str | None,
cbs_version: str | None,
cbl_version: str | None,
config_file: str,
) -> None:
topology_out = SCRIPT_DIR.parents[3] / "environment" / "aws" / "topology_setup" / "topology.json"
Expand All @@ -89,13 +99,15 @@ def main(
click.echo(f"Topology File : {topology_file}")
click.echo(f"SGW Version : {sgw_version}")
click.echo(f"CBS Version : {cbs_version}")
click.echo(f"CBL Version : {cbl_version or '(no test servers)'}")
click.echo()
generate_topology(
es_version=es_version,
topology_in=topology_file,
topology_out=topology_out,
sgw_version=sgw_version,
cbs_version=cbs_version,
cbl_version=cbl_version,
)

topology_obj = TopologyConfig(str(topology_out))
Expand Down
6 changes: 5 additions & 1 deletion jenkins/pipelines/QE/es/teardown.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
source $SCRIPT_DIR/../../shared/config.sh

pushd $AWS_ENVIRONMENT_DIR
uv run ./stop_backend.py
for d in "$QE_TESTS_DIR/edge_server" "$DEV_E2E_TESTS_DIR/edge_server"; do
move_artifacts "$d"
done

uv run ./stop_backend.py --topology topology_setup/topology.json
15 changes: 10 additions & 5 deletions jenkins/pipelines/QE/es/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ TOPOLOGY_NAME="${3:-es_sgw_topology.json}"
SGW_VERSION="${4:-}"
CBS_VERSION="${5:-}"
DATASET_VERSION="${6:-4.0}"
TEST_DIR="${7:-QE}" # QE | dev_e2e | both
TEST_DIR="${7:-QE}" # QE | dev_e2e | both
CBL_VERSION="${8:-}" # version-build for the topology's test servers (e.g. the localhost JS test server)
JS_ONLY="${9:-false}" # true: run only the tests that replicate with a CBL test server

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not the greatest name for an argument. The point here is not that the test servers are JS test servers (what about the other platforms?) but that you want the tests that involve a test server.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CBL JS replication tests with edge server were written to test the session API added in edge server and CBL JS. So JS_ONLY parameter helps me run tests to validate CBL JS RCs instead of running the entire edge server pipeline

TOPOLOGY_FILE="$SCRIPT_DIR/topologies/$TOPOLOGY_NAME"

if [ -z "$SGW_VERSION" ]; then
Expand Down Expand Up @@ -44,16 +46,19 @@ if [ "$TEST_NAME" != "." ]; then
PYTEST_FILTER=(-k "$TEST_NAME")
fi

if [ "$JS_ONLY" = "true" ]; then
SUITE_DIRS=("$QE_TESTS_DIR/edge_server")
PYTEST_FILTER+=(-m min_test_servers)
fi

echo "Setup backend..."
uv run $SCRIPT_DIR/setup_test.py $ES_VERSION $TOPOLOGY_FILE --sgw-version "${SGW_VERSION:-}" --cbs-version "${CBS_VERSION:-}"
uv run $SCRIPT_DIR/setup_test.py $ES_VERSION $TOPOLOGY_FILE --sgw-version "${SGW_VERSION:-}" --cbs-version "${CBS_VERSION:-}" --cbl-version "${CBL_VERSION:-}"

export COLUMNS=200
TEST_RESULT=0

# Each directory runs as its own pytest session against the same backend.
# A failure in one does not stop the next; the script fails if any failed.
for suite_dir in "${SUITE_DIRS[@]}"; do
echo "RUNNING COORDINATED TEST ($suite_dir, TEST_NAME=$TEST_NAME)"
echo "RUNNING COORDINATED TEST ($suite_dir, TEST_NAME=$TEST_NAME, JS_ONLY=$JS_ONLY)"
pushd "$suite_dir" >/dev/null

if uv run pytest -v --no-header -W ignore::DeprecationWarning --config "$QE_TESTS_DIR/config.json" --dataset-version "$DATASET_VERSION" ${PYTEST_FILTER[@]+"${PYTEST_FILTER[@]}"} .; then
Expand Down
17 changes: 17 additions & 0 deletions jenkins/pipelines/QE/es/topologies/1es_1js_topology.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "./../../../../../environment/aws/topology_setup/topology_schema.json",
"edge_servers": [
{
"version": "{{version}}"
}
],
"test_servers": [
{
"platform": "js",
"cbl_version": "{{version}}",
"location": "localhost",
"download": true
}
],
"logslurp": true
}
33 changes: 33 additions & 0 deletions jenkins/pipelines/QE/es/topologies/3es_1sgw_1js_topology.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"$schema": "./../../../../../environment/aws/topology_setup/topology_schema.json",
"edge_servers": [
{
"version": "{{version}}"
},
{
"version": "{{version}}"
},
{
"version": "{{version}}"
}
],
"clusters": [
{
"server_count": 1
}
],
"sync_gateways": [
{
"cluster": 0
}
],
"test_servers": [
{
"platform": "js",
"cbl_version": "{{version}}",
"location": "localhost",
"download": true
}
],
"logslurp": true
}
11 changes: 11 additions & 0 deletions tests/QE/edge_server/config/test_per_db_access_control.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
"enable_user_access_control": true,
"enable_anonymous_users": true,
"users": "/home/ec2-user/user/per_db_access_users.json",
"cors": {
"origin": [
"http://localhost:5173"
],
"headers": [
"Authorization",
"Content-Type",
"If-Match"
],
"max_age": 600
},
"databases": {
"enforced": {
"path": "/home/ec2-user/database/enforced.cblite2",
Expand Down
Loading