diff --git a/server/docker-compose.yml b/server/docker-compose.yml index ff43ee80074e..6a108e05637f 100644 --- a/server/docker-compose.yml +++ b/server/docker-compose.yml @@ -1,8 +1,21 @@ services: + proxy: + platform: linux/amd64/v3 + image: nginx:latest + depends_on: + - "alfred" + - "historian" + - "nexus" + volumes: + - ./routerlicious/nginx.conf:/etc/nginx/nginx.conf + ports: + - "3003:3003" + - "3002:3002" + - "3001:3001" alfred: image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/server:${ALFRED_IMAGE_TAG:-latest} - ports: - - "3003:3000" + expose: + - "3000" command: node packages/routerlicious/dist/alfred/www.js environment: - DEBUG=fluid:* @@ -11,8 +24,8 @@ services: restart: always nexus: image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/server:${ALFRED_IMAGE_TAG:-latest} - ports: - - "3002:3000" + expose: + - "3000" command: node packages/routerlicious/dist/nexus/www.js environment: - DEBUG=fluid:* @@ -63,15 +76,15 @@ services: restart: always historian: image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/historian:${HISTORIAN_IMAGE_TAG:-latest} - ports: - - "3001:3000" + expose: + - "3000" environment: - DEBUG=fluid:* - NODE_ENV=development - IS_FLUID_SERVER=true restart: always gitrest: - image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/gitrest:${HISTORIAN_IMAGE_TAG:-latest} + image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/gitrest:${GITREST_IMAGE_TAG:-latest} environment: - DEBUG=fluid:* - NODE_ENV=development @@ -80,7 +93,7 @@ services: - git:/home/node/documents restart: always git: - image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/gitssh:${HISTORIAN_IMAGE_TAG:-latest} + image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/gitssh:${GITSSH_IMAGE_TAG:-latest} ports: - "3022:22" volumes: diff --git a/server/routerlicious/docker-compose.yml b/server/routerlicious/docker-compose.yml index bfb9bd1a4ee0..54444317816e 100644 --- a/server/routerlicious/docker-compose.yml +++ b/server/routerlicious/docker-compose.yml @@ -1,5 +1,6 @@ services: proxy: + platform: linux/amd64/v3 image: nginx:latest volumes: - ./nginx.conf:/etc/nginx/nginx.conf @@ -105,7 +106,7 @@ services: - IS_FLUID_SERVER=true restart: always historian: - image: mcr.microsoft.com/fluidframework/routerlicious/historian:latest + image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/historian:${HISTORIAN_IMAGE_TAG:-latest} expose: - "3000" environment: @@ -114,7 +115,7 @@ services: - IS_FLUID_SERVER=true restart: always gitrest: - image: mcr.microsoft.com/fluidframework/routerlicious/gitrest:latest + image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/gitrest:${GITREST_IMAGE_TAG:-latest} environment: - DEBUG=fluid:* - NODE_ENV=development @@ -123,7 +124,7 @@ services: - git:/home/node/documents restart: always git: - image: mcr.microsoft.com/fluidframework/routerlicious/gitssh:latest + image: ${REGISTRY_URL:-mcr.microsoft.com}/fluidframework/routerlicious/gitssh:${GITSSH_IMAGE_TAG:-latest} ports: - "3022:22" volumes: diff --git a/server/routerlicious/package.json b/server/routerlicious/package.json index 70662c04b5e8..8c9f3f629bf3 100644 --- a/server/routerlicious/package.json +++ b/server/routerlicious/package.json @@ -160,6 +160,14 @@ }, "patchedDependencies": { "@microsoft/api-extractor@7.45.1": "patches/@microsoft__api-extractor@7.45.1.patch" - } + }, + "onlyBuiltDependencies": [ + "classic-level", + "core-js", + "node-rdkafka", + "snappy", + "unrs-resolver", + "zookeeper" + ] } } diff --git a/server/routerlicious/packages/routerlicious/config/config.json b/server/routerlicious/packages/routerlicious/config/config.json index ca2e3dd48c3b..8c24593917a7 100644 --- a/server/routerlicious/packages/routerlicious/config/config.json +++ b/server/routerlicious/packages/routerlicious/config/config.json @@ -73,7 +73,7 @@ "endpoint": "zookeeper:2181" }, "storage": { - "enableWholeSummaryUpload": false, + "enableWholeSummaryUpload": true, "ephemeralDocumentTTLSec": 86400, "storageUrl": "http://gitrest:3000" }, diff --git a/tools/pipelines/templates/include-test-real-service.yml b/tools/pipelines/templates/include-test-real-service.yml index 3579bdcb38ef..ebc2a0fd777d 100644 --- a/tools/pipelines/templates/include-test-real-service.yml +++ b/tools/pipelines/templates/include-test-real-service.yml @@ -20,7 +20,7 @@ parameters: # Variables to be set in the stage that runs tests - name: stageVariables type: object - default: + default: {} # If true, the stage that uploads pipeline telemetry to Kusto will include a task to upload # test pass rate telemetry. @@ -49,7 +49,7 @@ parameters: - name: env type: object - default: + default: {} - name: splitTestVariants type: object @@ -80,6 +80,7 @@ parameters: type: string default: "" +# If provided, this value is passed directly to the "condition" key of the stage in this file. - name: condition type: string default: true @@ -98,12 +99,6 @@ parameters: type: boolean default: false -# Custom steps specified by the "caller" of this template, for any additional things that need to be done -# after the steps in this template complete. -- name: additionalSteps - type: stepList - default: [] - # If true, the versions of our packages installed for compat testing will be cached. - name: cacheCompatVersionsInstalls type: boolean @@ -126,6 +121,25 @@ parameters: - none - sequential +# if true, the FluidFramework repo will be checked out and a docker-compose env will be spun up for testing +- name: runAgainstDocker + type: boolean + default: false + +# Tags for docker environment setup +- name: alfredImageTag + type: string + default: 'latest' +- name: historianImageTag + type: string + default: 'latest' +- name: gitrestImageTag + type: string + default: 'latest' +- name: gitsshImageTag + type: string + default: 'latest' + stages: - stage: ${{ parameters.stageId}} ${{ if ne(parameters.lockBehavior, 'none') }}: @@ -152,8 +166,16 @@ stages: # basic ANSI color support though, so force that in the pipeline - name: FORCE_COLOR value: 1 + - name: pipelineHostPath + ${{ if eq(parameters.runAgainstDocker, true) }}: + # Running against docker means we'll check out the FluidFramework repo as well as ff_pipeline_host + # When multiple repos are checked out, they are checked out to $(Build.SourcesDirectory)/ + value: $(Build.SourcesDirectory)/ff_pipeline_host + ${{ else }}: + value: $(Build.SourcesDirectory) + - name: testPackageDir - value: '$(Build.SourcesDirectory)/node_modules/${{ parameters.testPackage }}' + value: '${{ variables.pipelineHostPath }}/node_modules/${{ parameters.testPackage }}' - name: testPackageFilePattern value: ${{ replace(replace(parameters.testPackage, '@', '' ), '/', '-') }}-[0-9]*.tgz # Note that this path must match the path that the packed packages are saved to in the build pipeline. @@ -164,7 +186,6 @@ stages: value: true - name: artifactPipeline value: Build - client packages - steps: # Setup - checkout: ff_pipeline_host @@ -208,6 +229,7 @@ stages: Pipeline Parameters: poolBuild=${{ parameters.poolBuild }} testPackage=${{ parameters.testPackage }} + runAgainstDocker=${{ parameters.runAgainstDocker }} Pipeline Variables: isTestBranch=${{ variables.isTestBranch }} @@ -219,20 +241,47 @@ stages: testFileTarName=${{ parameters.testFileTarName }} artifactPipeline=${{ variables.artifactPipeline }} artifactBuildId=${{ parameters.artifactBuildId }} + pipelineHostPath=${{ variables.pipelineHostPath }} " - template: /tools/pipelines/templates/include-use-node-version.yml@self - template: /tools/pipelines/templates/include-install-pnpm.yml@self parameters: - buildDirectory: $(Build.SourcesDirectory) + buildDirectory: ${{ variables.pipelineHostPath }} - template: /tools/pipelines/templates/include-setup-npmrc-for-download.yml@self + # Set up Docker environment if running against docker + - ${{ if eq(parameters.runAgainstDocker, true) }}: + # Checks out FluidFramework repo + - checkout: self + clean: true + - task: Docker@2 + displayName: 'Login to container registry' + inputs: + containerRegistry: 'Fluid Container Registry' + command: 'login' + - task: DockerCompose@1 + displayName: 'Start routerlicious environment in docker' + inputs: + containerregistrytype: 'Container Registry' + dockerComposeFile: $(Build.SourcesDirectory)/FluidFramework/server/docker-compose.yml + action: 'Run a Docker Compose command' + dockerComposeCommand: 'up -d' + projectName: 'routerlicious' + env: + REGISTRY_URL: fluidcr.azurecr.io/build + ALFRED_IMAGE_TAG: ${{ parameters.alfredImageTag }} + HISTORIAN_IMAGE_TAG: ${{ parameters.historianImageTag }} + GITREST_IMAGE_TAG: ${{ parameters.gitrestImageTag }} + GITSSH_IMAGE_TAG: ${{ parameters.gitsshImageTag }} + - task: Bash@3 displayName: Install base dependencies inputs: targetType: 'inline' + workingDirectory: ${{ variables.pipelineHostPath }} script: | set -eu -o pipefail pnpm install @@ -262,7 +311,7 @@ stages: displayName: Initialize inputs: targetType: 'inline' - workingDirectory: $(Build.SourcesDirectory) + workingDirectory: ${{ variables.pipelineHostPath }} script: | set -eu -o pipefail if [[ `ls -1 ${{ variables.testPackagePathPattern }} | wc -l` -eq 1 ]]; then @@ -274,13 +323,14 @@ stages: fi # Install test package - task: Bash@3 - displayName: 'pnpm install' + displayName: 'pnpm install test package' # ADO feeds have latency on the order of minutes before packages are available downstream. See: # https://learn.microsoft.com/en-us/azure/devops/artifacts/concepts/upstream-sources?view=azure-devops#upstream-sources-health-status # This pipeline installs packages which were published very recently relative to its runtime, hence the rather high retry count here. retryCountOnTaskFailure: 10 inputs: targetType: 'inline' + workingDirectory: ${{ variables.pipelineHostPath }} script: 'pnpm install $(Initialize.testPackageTgz)' # Download Test Files & Install Extra Dependencies @@ -310,8 +360,8 @@ stages: - task: Bash@3 displayName: Unpack test files inputs: - workingDirectory: $(Build.SourcesDirectory)/node_modules/${{ parameters.testPackage }} targetType: 'inline' + workingDirectory: ${{ variables.pipelineHostPath }}/node_modules/${{ parameters.testPackage }} script: | set -eu -o pipefail @@ -328,15 +378,15 @@ stages: - template: /tools/pipelines/templates/include-copy-dev-dependencies.yml@self parameters: - sourcePackageLocation: $(Build.SourcesDirectory)/node_modules/${{ parameters.testPackage }} - destPackageLocation: $(Build.SourcesDirectory) + sourcePackageLocation: ${{ variables.pipelineHostPath }}/node_modules/${{ parameters.testPackage }} + destPackageLocation: ${{ variables.pipelineHostPath }} - ${{ if eq(parameters.cacheCompatVersionsInstalls, true) }}: - task: Bash@3 displayName: Compute compat versions install location and version inputs: targetType: 'inline' - workingDirectory: $(Build.SourcesDirectory)/node_modules/@fluid-private/test-end-to-end-tests + workingDirectory: ${{ variables.pipelineHostPath }}/node_modules/@fluid-private/test-end-to-end-tests # Using import.meta.resolve to compute this is more resilient to different install tree types. # Also note that test-version-utils is esm-only, so cannot be loaded with require. script: | @@ -364,7 +414,7 @@ stages: timeoutInMinutes: 3 continueOnError: true inputs: - key: '"compat-version-installs" | "$(Agent.OS)" | "${{ parameters.testCommand }}" | "${{ variant.name }}" | $(compatVersionCacheKey)' + key: '"compat-version-installs" | "$(Agent.OS)" | "${{ parameters.testCommand }}" | "${{ variant.name }}" | "$(compatVersionCacheKey)"' path: $(compatVersionInstallsPath) # Only check out tenants from the tenant pool if we are running tests against ODSP @@ -413,7 +463,7 @@ stages: login__odsp__test__tenants: $(tenantCreds) inputs: command: 'custom' - workingDir: $(Build.SourcesDirectory)/node_modules/${{ parameters.testPackage }} + workingDir: ${{ variables.pipelineHostPath }}/node_modules/${{ parameters.testPackage }} customCommand: 'run ${{ parameters.testCommand }} -- ${{ variant.flags }}' - ${{ if eq(parameters.skipTestResultPublishing, false) }}: @@ -455,7 +505,7 @@ stages: - task: PublishPipelineArtifact@1 displayName: Publish Artifact - Tinylicious Log inputs: - targetPath: '$(Build.SourcesDirectory)/node_modules/${{ parameters.testPackage }}/tinylicious.log' + targetPath: '${{ variables.pipelineHostPath }}/node_modules/${{ parameters.testPackage }}/tinylicious.log' artifactName: 'tinyliciousLog_attempt-$(System.JobAttempt)' publishLocation: 'pipeline' condition: always() @@ -494,7 +544,17 @@ stages: # parameters: # buildDirectory: ${{ variables.testPackageDir }} - - ${{ parameters.additionalSteps }} + # Stop the docker environment if running against it + - ${{ if eq(parameters.runAgainstDocker, true) }}: + - task: DockerCompose@1 + displayName: 'Stop routerlicious environment in docker' + condition: always() + inputs: + containerregistrytype: 'Container Registry' + dockerComposeFile: $(Build.SourcesDirectory)/FluidFramework/server/docker-compose.yml + action: 'Run a Docker Compose command' + dockerComposeCommand: 'down' + projectName: 'routerlicious' - template: /tools/pipelines/templates/include-upload-npm-logs.yml@self diff --git a/tools/pipelines/test-real-service.yml b/tools/pipelines/test-real-service.yml index 4cf6a7ca02ca..b8dd4d380110 100644 --- a/tools/pipelines/test-real-service.yml +++ b/tools/pipelines/test-real-service.yml @@ -20,7 +20,7 @@ parameters: resources: pipelines: - - pipeline: client # Name of the pipeline resource + - pipeline: client source: Build - client packages branch: main # Default branch for manual/scheduled triggers if none is selected trigger: @@ -29,6 +29,18 @@ resources: - main - next - lts + - pipeline: routerlicious + source: server-routerlicious + branch: main # Default branch for manual/scheduled triggers if none is selected + - pipeline: historian + source: server-historian + branch: main # Default branch for manual/scheduled triggers if none is selected + - pipeline: gitrest + source: server-gitrest + branch: main # Default branch for manual/scheduled triggers if none is selected + - pipeline: gitssh + source: server-gitssh + branch: main # Default branch for manual/scheduled triggers if none is selected repositories: - repository: ff_pipeline_host type: git @@ -128,6 +140,45 @@ stages: FLUID_TEST_LOGGER_PKG_SPECIFIER: '@ff-internal/aria-logger' # Contains createTestLogger impl to inject FLUID_LOGGER_PROPS: '{ "displayName": "${{variables.pipelineIdentifierForTelemetry}}"}' + # end-to-end tests docker + - template: templates/include-test-real-service.yml + parameters: + stageId: e2e_docker + stageDisplayName: e2e - docker + poolBuild: Large-eastus2 # Need Large pool for full-compat matrix + testPackage: ${{ variables.testPackage }} + testWorkspace: ${{ variables.testWorkspace }} + artifactBuildId: $(resources.pipeline.client.runID) + continueOnError: true + testCommand: test:realsvc:r11s:docker + stageVariables: + - group: container-registry-info + splitTestVariants: + - name: Non-compat + flags: --compatVersion=0 + - name: N-1 + flags: --compatVersion=-1 + - name: LTS + flags: --compatVersion=LTS + - name: Cross-Client + flags: --compatVersion=CROSS_CLIENT + cacheCompatVersionsInstalls: true + uploadTestPassRateTelemetry: true + pipelineIdentifierForTelemetry: ${{ variables.pipelineIdentifierForTelemetry }} + + # Checks out the FluidFramework source so we can run the docker service + runAgainstDocker: true + + # Docker tags to use when constructing the docker environment + alfredImageTag: 0.0.$(resources.pipeline.routerlicious.runID) + historianImageTag: 0.0.$(resources.pipeline.historian.runID) + gitrestImageTag: 0.0.$(resources.pipeline.gitrest.runID) + gitsshImageTag: 0.0.$(resources.pipeline.gitssh.runID) + + env: + FLUID_TEST_LOGGER_PKG_SPECIFIER: '@ff-internal/aria-logger' # Contains createTestLogger impl to inject + FLUID_LOGGER_PROPS: '{ "displayName": "${{variables.pipelineIdentifierForTelemetry}}"}' + # end-to-end tests AFR - template: /tools/pipelines/templates/include-test-real-service.yml@self parameters: