diff --git a/eng/pipelines/common/checkout-and-evaluate-paths.yml b/eng/pipelines/common/checkout-and-evaluate-paths.yml new file mode 100644 index 0000000000000..455645b49378c --- /dev/null +++ b/eng/pipelines/common/checkout-and-evaluate-paths.yml @@ -0,0 +1,80 @@ +parameters: + extraSubsets: '' + +jobs: +- template: /eng/pipelines/common/checkout-job.yml + parameters: + paths: + - subset: coreclr + include: + - src/libraries/System.Private.CoreLib/* + - src/libraries/Native/Unix/System.Globalization.Native/* + - src/libraries/Native/Unix/Common/* + exclude: + - eng/Version.Details.xml + - '*.md' + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + - docs/* + - src/installer/* + - src/mono/* + - src/libraries/* + - eng/pipelines/installer/* + - eng/pipelines/mono/* + - eng/pipelines/libraries/* + - subset: mono + include: + - src/libraries/System.Private.CoreLib/* + - src/libraries/Native/Unix/System.Globalization.Native/* + - src/libraries/Native/Unix/Common/* + exclude: + - eng/Version.Details.xml + - '*.md' + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + - docs/* + - src/installer/* + - src/coreclr/* + - src/libraries/* + - eng/pipelines/installer/* + - eng/pipelines/coreclr/* + - eng/pipelines/libraries/* + - subset: libraries + exclude: + - eng/Version.Details.xml + - '*.md' + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + - docs/* + - src/installer/* + - src/mono/* + - src/coreclr/* + - eng/pipelines/coreclr/* + - eng/pipelines/mono/* + - eng/pipelines/installer/* + - subset: runtimetests + include: + - src/tests/* + - src/coreclr/tests/* + - subset: installer + include: + - docs/manpages/* + exclude: + - eng/Version.Details.xml + - '*.md' + - LICENSE.TXT + - PATENTS.TXT + - THIRD-PARTY-NOTICES.TXT + - docs/* + - src/coreclr/* + - src/mono/* + - src/libraries/* + - eng/pipelines/coreclr/* + - eng/pipelines/mono/* + - eng/pipelines/libraries/* + + - ${{ if ne(parameters.extraSubsets, '') }}: + - ${{ parameters.extraSubsets }} diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index d002de384703b..efdd1e83addb3 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -14,6 +14,7 @@ parameters: pool: '' platform: '' condition: true + shouldContinueOnError: false isOfficialBuild: false runtimeFlavor: 'coreclr' helixQueues: '' @@ -103,6 +104,7 @@ jobs: targetRid: ${{ parameters.targetRid }} nameSuffix: ${{ parameters.nameSuffix }} platform: ${{ parameters.platform }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} ${{ insert }}: ${{ parameters.extraStepsParameters }} - task: PublishBuildArtifacts@1 diff --git a/eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml b/eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml index b5390fda2a57e..49ac79e3620a4 100644 --- a/eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml +++ b/eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml @@ -22,6 +22,7 @@ parameters: timeoutInMinutes: '' enableMicrobuild: '' gatherAssetManifests: false + shouldContinueOnError: false steps: @@ -38,6 +39,7 @@ steps: osSubgroup: ${{ parameters.osSubgroup}} coreClrRepoRoot: $(Build.SourcesDirectory)/src/coreclr runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} ${{ if eq(variables['System.TeamProject'], 'public') }}: creator: $(Build.DefinitionName) diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index 5fd480b3a7250..d13e82b2121b1 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -21,6 +21,7 @@ parameters: pool: '' runtimeFlavor: 'coreclr' runtimeFlavorDisplayName: 'CoreCLR' + shouldContinueOnError: false dependsOn: [] ### Test run job @@ -305,6 +306,7 @@ jobs: osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup}} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} ${{ if eq(variables['System.TeamProject'], 'public') }}: creator: $(Build.DefinitionName) diff --git a/eng/pipelines/common/templates/runtimes/send-to-helix-inner-step.yml b/eng/pipelines/common/templates/runtimes/send-to-helix-inner-step.yml index 1427e68a273e7..2ea51577d4fe9 100644 --- a/eng/pipelines/common/templates/runtimes/send-to-helix-inner-step.yml +++ b/eng/pipelines/common/templates/runtimes/send-to-helix-inner-step.yml @@ -5,6 +5,7 @@ parameters: condition: '' displayName: '' environment: {} + shouldContinueOnError: false steps: - ${{ if eq(parameters.osGroup, 'windows') }}: @@ -17,6 +18,7 @@ steps: displayName: ${{ parameters.displayName }} (Windows) condition: ${{ and(ne(parameters.condition, false), ne(parameters.sendParams, '')) }} env: ${{ parameters.environment }} + continueOnError: ${{ parameters.shouldContinueOnError }} - ${{ if ne(parameters.osGroup, 'windows') }}: # TODO: Remove and consolidate this when we move to arcade via init-tools.sh. @@ -32,3 +34,4 @@ steps: displayName: ${{ parameters.displayName }} (Unix) condition: ${{ and(ne(parameters.condition, false), ne(parameters.sendParams, '')) }} env: ${{ parameters.environment }} + continueOnError: ${{ parameters.shouldContinueOnError }} diff --git a/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml b/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml index febcfa4016dbb..3448f6e51fba5 100644 --- a/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml +++ b/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml @@ -25,6 +25,8 @@ parameters: gcSimulatorTests: '' runtimeFlavorDisplayName: 'CoreCLR' runtimeVariant: '' + shouldContinueOnError: false + steps: - template: send-to-helix-inner-step.yml @@ -33,6 +35,7 @@ steps: restoreParams: /p:DotNetPublishToBlobFeed=true -restore -projects $(Build.SourcesDirectory)$(dir)eng$(dir)empty.csproj sendParams: ${{ parameters.helixProjectArguments }} /maxcpucount /bl:$(Build.SourcesDirectory)/artifacts/log/SendToHelix.binlog /p:TargetArchitecture=${{ parameters.archType }} /p:TargetOS=${{ parameters.osGroup }} /p:TargetOSSubgroup=${{ parameters.osSubgroup }} /p:Configuration=${{ parameters.buildConfig }} condition: and(succeeded(), ${{ parameters.condition }}) + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} displayName: ${{ parameters.displayName }} environment: _Creator: ${{ parameters.creator }} diff --git a/eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml b/eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml index 462fe65331083..ed6022360c55a 100644 --- a/eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml +++ b/eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml @@ -28,6 +28,7 @@ parameters: timeoutInMinutes: '' enableMicrobuild: '' gatherAssetManifests: false + shouldContinueOnError: false steps: @@ -44,6 +45,7 @@ steps: osSubgroup: ${{ parameters.osSubgroup}} coreClrRepoRoot: $(Build.SourcesDirectory)/src/coreclr runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} ${{ if eq(variables['System.TeamProject'], 'public') }}: creator: $(Build.DefinitionName) diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index d8df89ed73ac7..48d9ae2430cff 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -17,6 +17,9 @@ jobs: runtimeFlavorDisplayName: 'CoreCLR' ${{ if eq(parameters.jobParameters.runtimeFlavor, 'mono') }}: runtimeFlavorDisplayName: 'Mono' + + shouldContinueOnError: ${{ endsWith(variables['Build.DefinitionName'], 'staging') }} + variables: # Disable component governance in our CI builds. These builds are not shipping nor # are they a service. Also the component governance jobs issue lots of inconsequential diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index dfd5f9bd3ef03..c793b86c7d1e0 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -8,6 +8,7 @@ parameters: pool: '' platform: '' runtimeFlavorDisplayName: '' + shouldContinueOnError: false jobParameters: {} jobs: @@ -19,6 +20,7 @@ jobs: archType: ${{ parameters.archType }} container: ${{ parameters.container }} pool: ${{ parameters.pool }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} helixQueues: diff --git a/eng/pipelines/installer/jobs/base-job.yml b/eng/pipelines/installer/jobs/base-job.yml index 50db8eeaacd24..6db5081a32689 100644 --- a/eng/pipelines/installer/jobs/base-job.yml +++ b/eng/pipelines/installer/jobs/base-job.yml @@ -8,6 +8,7 @@ parameters: crossrootfsDir: '' timeoutInMinutes: 120 condition: true + shouldContinueOnError: false container: '' buildSteps: [] dependsOn: [] @@ -377,11 +378,13 @@ jobs: - ${{ if ne(parameters.osGroup, 'OSX') }}: - script: $(BaseJobBuildCommand) displayName: Build + continueOnError: ${{ and(eq(variables.SkipTests, false), parameters.shouldContinueOnError) }} # Build corehost, sign and add entitlements to MacOS binaries - ${{ if eq(parameters.osGroup, 'OSX') }}: - script: $(BaseJobBuildCommand) -subset host.native displayName: Build CoreHost + continueOnError: ${{ and(eq(variables.SkipTests, false), parameters.shouldContinueOnError) }} - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - template: /eng/pipelines/common/macos-sign-with-entitlements.yml @@ -396,6 +399,7 @@ jobs: - script: $(BaseJobBuildCommand) -subset host.pkg+host.tools+packs displayName: Build and Package + continueOnError: ${{ and(eq(variables.SkipTests, false), parameters.shouldContinueOnError) }} - ${{ if in(parameters.osGroup, 'OSX', 'iOS','tvOS') }}: - script: | diff --git a/eng/pipelines/libraries/build-job.yml b/eng/pipelines/libraries/build-job.yml index c0dd92d3e0555..d54cbb1298baf 100644 --- a/eng/pipelines/libraries/build-job.yml +++ b/eng/pipelines/libraries/build-job.yml @@ -24,6 +24,7 @@ parameters: preBuildSteps: [] container: '' condition: true + shouldContinueOnError: false variables: {} pool: '' runTests: false @@ -142,6 +143,7 @@ jobs: buildConfig: ${{ parameters.buildConfig }} helixQueues: ${{ parameters.helixQueues }} testScope: ${{ parameters.testScope }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} creator: dotnet-bot testRunNamePrefixSuffix: $(_testRunNamePrefixSuffix) extraHelixArguments: $(_extraHelixArguments) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 84f09c6ba8fcd..49c39a2d949d6 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -8,6 +8,7 @@ parameters: pool: '' platform: '' runtimeFlavorDisplayName: '' + shouldContinueOnError: false jobParameters: {} jobs: @@ -19,6 +20,7 @@ jobs: archType: ${{ parameters.archType }} container: ${{ parameters.container }} pool: ${{ parameters.pool }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} helixQueues: diff --git a/eng/pipelines/libraries/helix.yml b/eng/pipelines/libraries/helix.yml index 706f82e19b068..8a3371da1e78c 100644 --- a/eng/pipelines/libraries/helix.yml +++ b/eng/pipelines/libraries/helix.yml @@ -11,6 +11,7 @@ parameters: interpreter: '' condition: always() extraHelixArguments: '' + shouldContinueOnError: false scenarios: '' steps: @@ -30,6 +31,7 @@ steps: /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog displayName: Send to Helix condition: and(succeeded(), ${{ parameters.condition }}) + continueOnError: ${{ parameters.shouldContinueOnError }} env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops HelixTargetQueues: ${{ join('+', parameters.helixQueues) }} # Pass queues to MSBuild as env var to avoid need of escaping them diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index 11e4341c7af99..9f8e8907a99a9 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -18,6 +18,7 @@ parameters: dependsOnTestBuildConfiguration: Debug dependsOnTestArchitecture: x64 condition: true + shouldContinueOnError: false variables: {} # coreclrTestGroup: if empty, then a normal, default test run is created. If set, it indicates a set of # stress modes that each test will be run with. This is the same usage as 'testGroup' in @@ -120,6 +121,7 @@ jobs: helixQueues: ${{ parameters.helixQueues }} testScope: ${{ parameters.testScope }} interpreter: ${{ parameters.interpreter }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} creator: dotnet-bot testRunNamePrefixSuffix: $(_testRunNamePrefixSuffix) extraHelixArguments: $(_extraHelixArguments) diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml new file mode 100644 index 0000000000000..bd3c0f732cb1e --- /dev/null +++ b/eng/pipelines/runtime-staging.yml @@ -0,0 +1,110 @@ +# The staging pipeline only makes sense to run it on PRs. +trigger: none + +pr: + branches: + include: + - master + - dev/infrastructure + - release/*.* + paths: + include: + - '*' + - docs/manpages/* + exclude: + - eng/Version.Details.xml + - .github/* + - docs/* + - CODE-OF-CONDUCT.md + - CONTRIBUTING.md + - LICENSE.TXT + - PATENTS.TXT + - README.md + - SECURITY.md + - THIRD-PARTY-NOTICES.TXT + +variables: + - template: /eng/pipelines/common/variables.yml + +jobs: +# +# Checkout repository and evaluate paths +# +- template: /eng/pipelines/common/checkout-and-evaluate-paths.yml + +# +# Build the whole product using Mono and run libraries tests +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Android_x64 + variables: + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.checkout.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.checkout.outputs['SetPathVars_mono.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + timeoutInMinutes: 120 + condition: >- + or( + eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.checkout.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isFullMatrix'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isFullMatrix'], true)) + +# +# Build the whole product using Mono for Android and run runtime tests with Android emulator +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Android_x64 + variables: + - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: pr/dotnet/runtime/$(Build.SourceBranch) + - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: ci/dotnet/runtime/$(Build.SourceBranch) + - name: timeoutPerTestInMinutes + value: 60 + - name: timeoutPerTestCollectionInMinutes + value: 300 + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono_RuntimeTests + buildArgs: -s mono+libs -c $(_BuildConfig) + timeoutInMinutes: 300 + condition: >- + or( + eq(dependencies.checkout.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isFullMatrix'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index e84d08e83ef47..ccce024e27e04 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -52,81 +52,9 @@ variables: jobs: # -# Checkout repository +# Checkout repository and evaluate paths # -- template: /eng/pipelines/common/checkout-job.yml - parameters: - paths: - - subset: coreclr - include: - - src/libraries/System.Private.CoreLib/* - - src/libraries/Native/Unix/System.Globalization.Native/* - - src/libraries/Native/Unix/Common/* - exclude: - - eng/Version.Details.xml - - '*.md' - - LICENSE.TXT - - PATENTS.TXT - - THIRD-PARTY-NOTICES.TXT - - docs/* - - src/installer/* - - src/mono/* - - src/libraries/* - - eng/pipelines/installer/* - - eng/pipelines/mono/* - - eng/pipelines/libraries/* - - subset: mono - include: - - src/libraries/System.Private.CoreLib/* - - src/libraries/Native/Unix/System.Globalization.Native/* - - src/libraries/Native/Unix/Common/* - exclude: - - eng/Version.Details.xml - - '*.md' - - LICENSE.TXT - - PATENTS.TXT - - THIRD-PARTY-NOTICES.TXT - - docs/* - - src/installer/* - - src/coreclr/* - - src/libraries/* - - eng/pipelines/installer/* - - eng/pipelines/coreclr/* - - eng/pipelines/libraries/* - - subset: libraries - exclude: - - eng/Version.Details.xml - - '*.md' - - LICENSE.TXT - - PATENTS.TXT - - THIRD-PARTY-NOTICES.TXT - - docs/* - - src/installer/* - - src/mono/* - - src/coreclr/* - - eng/pipelines/coreclr/* - - eng/pipelines/mono/* - - eng/pipelines/installer/* - - subset: runtimetests - include: - - src/tests/* - - src/coreclr/tests/* - - subset: installer - include: - - docs/manpages/* - exclude: - - eng/Version.Details.xml - - '*.md' - - LICENSE.TXT - - PATENTS.TXT - - THIRD-PARTY-NOTICES.TXT - - docs/* - - src/coreclr/* - - src/mono/* - - src/libraries/* - - eng/pipelines/coreclr/* - - eng/pipelines/mono/* - - eng/pipelines/libraries/* +- template: /eng/pipelines/common/checkout-and-evaluate-paths.yml # # Build CoreCLR checked @@ -354,7 +282,6 @@ jobs: runtimeFlavor: mono platforms: - Android_arm64 - - Android_x64 - iOS_x64 variables: # map dependencies variables to local variables @@ -422,44 +349,6 @@ jobs: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) -# -# Build the whole product using Mono for Android and run runtime tests with Android emulator -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Android_x64 - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 60 - - name: timeoutPerTestCollectionInMinutes - value: 300 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 300 - condition: >- - or( - eq(dependencies.checkout.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - # # Build Mono and Installer on LLVMJIT mode #