diff --git a/.github/actions/publish-docker-hub/action.yml b/.github/actions/publish-docker-hub/action.yml
new file mode 100644
index 00000000..a74efc18
--- /dev/null
+++ b/.github/actions/publish-docker-hub/action.yml
@@ -0,0 +1,29 @@
+name: "Publish to Docker"
+description: "Pushes built artifacts to Docker"
+inputs:
+ build_configuration:
+ description: "Debug/Release"
+ required: true
+ dotnet_version:
+ description: "net45/net46/net471/net48/etc"
+ required: true
+ username:
+ description: "Docker registry username"
+ required: true
+ password:
+ description: "Docker registry password"
+ required: true
+runs:
+ using: "composite"
+ steps:
+ - uses: mr-smithers-excellent/docker-build-push@v5
+ name: Build & push Docker image
+ with:
+ image: antonytm/dianoga-assets
+ tags: 6.0.0-beta.2-${{ inputs.dotnet_version }}-${{ inputs.build_configuration }}-${{ github.run_number }}, latest-${{ inputs.dotnet_version }}-${{ inputs.build_configuration }}
+ registry: docker.io
+ dockerfile: Dockerfile
+ username: ${{ inputs.username }}
+ password: ${{ inputs.password }}
+ buildArgs: |
+ BUILD_CONFIGURATION=${{ inputs.build_configuration }}, DOTNET_VERSION_ARG=${{ inputs.dotnet_version }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET452-Debug.yml b/.github/workflows/Dianoga-Docker-NET452-Debug.yml
new file mode 100644
index 00000000..9025dfc9
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET452-Debug.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.5.2, Debug
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Debug
+ DIANOGA_DOTNET_VERSION: net452
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET452-Release.yml b/.github/workflows/Dianoga-Docker-NET452-Release.yml
new file mode 100644
index 00000000..7fee88e7
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET452-Release.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.5.2, Release
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Release
+ DIANOGA_DOTNET_VERSION: net452
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET462-Debug.yml b/.github/workflows/Dianoga-Docker-NET462-Debug.yml
new file mode 100644
index 00000000..e71dad0d
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET462-Debug.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.6.2, Debug
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Debug
+ DIANOGA_DOTNET_VERSION: net462
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET462-Release.yml b/.github/workflows/Dianoga-Docker-NET462-Release.yml
new file mode 100644
index 00000000..c63dad3e
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET462-Release.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.6.2, Release
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Release
+ DIANOGA_DOTNET_VERSION: net462
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET471-Debug.yml b/.github/workflows/Dianoga-Docker-NET471-Debug.yml
new file mode 100644
index 00000000..bac930db
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET471-Debug.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.7.1, Debug
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Debug
+ DIANOGA_DOTNET_VERSION: net471
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET471-Release.yml b/.github/workflows/Dianoga-Docker-NET471-Release.yml
new file mode 100644
index 00000000..2cb91373
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET471-Release.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.7.1, Release
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Release
+ DIANOGA_DOTNET_VERSION: net471
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET48-Debug.yml b/.github/workflows/Dianoga-Docker-NET48-Debug.yml
new file mode 100644
index 00000000..44043c14
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET48-Debug.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.8, Debug
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Debug
+ DIANOGA_DOTNET_VERSION: net48
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/Dianoga-Docker-NET48-Release.yml b/.github/workflows/Dianoga-Docker-NET48-Release.yml
new file mode 100644
index 00000000..c44e0b20
--- /dev/null
+++ b/.github/workflows/Dianoga-Docker-NET48-Release.yml
@@ -0,0 +1,20 @@
+name: Dianoga Docker CI, .NET 4.8, Release
+on:
+ push:
+ branches: [ feature/docker ]
+env:
+ BUILD_CONFIGURATION: Release
+ DIANOGA_DOTNET_VERSION: net48
+jobs:
+ build:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run custom action
+ uses: ./.github/actions/publish-docker-hub
+ with:
+ build_configuration: ${{ env.BUILD_CONFIGURATION }}
+ dotnet_version: ${{ env.DIANOGA_DOTNET_VERSION }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 185cef10..d69680df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,5 @@ src/Dianoga.Tests/Optimizers/Pipelines/DianogaSvg/SVGO
# NuGet packages
packages/*
!packages/repositories.config
-Build/*.nupkg
\ No newline at end of file
+Build/*.nupkg
+/integration-tests/.env
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..acc80309
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,50 @@
+# escape=`
+
+ARG BASE_IMAGE=mcr.microsoft.com/windows/nanoserver:1809
+ARG BUILD_IMAGE=mcr.microsoft.com/dotnet/framework/sdk:4.8
+
+FROM ${BUILD_IMAGE} AS build-env
+ARG BUILD_CONFIGURATION=
+ARG DOTNET_VERSION_ARG=
+
+WORKDIR /
+# Add Sitecore Nuget source
+RUN dotnet nuget add source https://sitecore.myget.org/F/sc-packages/api/v3/index.json
+
+# Copy csproj and restore as distinct layers
+COPY *.sln ./
+COPY src/Dianoga/Dianoga.csproj ./src/Dianoga/
+COPY src/Dianoga.Tests/Dianoga.Tests.csproj ./src/Dianoga.Tests/
+RUN dotnet restore
+
+# Copy everything else and build
+COPY src ./src
+RUN dotnet build -c $env:BUILD_CONFIGURATION
+RUN mkdir ./src/bin
+RUN Copy ./src/Dianoga/bin/$env:BUILD_CONFIGURATION/$env:DOTNET_VERSION_ARG/Dianoga.* ./src/bin/
+RUN Copy ./src/Dianoga/bin/$env:BUILD_CONFIGURATION/$env:DOTNET_VERSION_ARG/System.Threading.Tasks.Dataflow.dll ./src/bin/
+
+FROM ${BASE_IMAGE}
+
+# Copy Dianoga dll and pdb (if present)
+COPY --from=build-env /src/bin/ ./module/cd/content/bin/
+COPY --from=build-env /src/bin/ ./module/cm/content/bin/
+
+
+# Copy Dianoga Tools
+ARG src="/src/Dianoga/Dianoga Tools"
+ARG target="./module/cd/content/App_Data/Dianoga Tools"
+COPY --from=build-env ${src} ${target}
+
+ARG src="/src/Dianoga/Dianoga Tools"
+ARG target="./module/cd/content/App_Data/Dianoga Tools"
+COPY --from=build-env ${src} ${target}
+
+# Copy Configs
+ARG src="/src/Dianoga/Default Config Files"
+ARG target="./module/cm/content/App_Config/Include/Dianoga"
+COPY --from=build-env ${src} ${target}
+
+ARG src="/src/Dianoga/Default Config Files"
+ARG target="./module/cd/content/App_Config/Include/Dianoga"
+COPY --from=build-env ${src} ${target}
diff --git a/integration-tests/.dockerignore b/integration-tests/.dockerignore
new file mode 100644
index 00000000..484b11c5
--- /dev/null
+++ b/integration-tests/.dockerignore
@@ -0,0 +1,17 @@
+# folders
+.git
+.gitignore
+.vs
+.vscode
+build
+docker
+packages
+**/bin/
+**/obj/
+**/out/
+
+# files
+*Dockerfile
+docker-compose*
+**/*.md
+*.ps1
\ No newline at end of file
diff --git a/integration-tests/Dockerfile b/integration-tests/Dockerfile
new file mode 100644
index 00000000..defe156c
--- /dev/null
+++ b/integration-tests/Dockerfile
@@ -0,0 +1,49 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG BUILD_IMAGE
+
+FROM ${BUILD_IMAGE} AS prep
+ARG BUILD_CONFIGURATION
+RUN echo $env:BUILD_CONFIGURATION
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Gather only artifacts necessary for NuGet restore, retaining directory structure
+COPY *.sln NuGet.config Directory.Build.targets Packages.props nuget\
+COPY src\ \temp\
+RUN Invoke-Expression 'robocopy C:\temp C:\nuget\src /s /ndl /njh /njs *.csproj *.scproj packages.config'
+
+FROM ${BUILD_IMAGE} AS builder
+
+ARG BUILD_CONFIGURATION
+RUN echo $env:BUILD_CONFIGURATION
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Create an empty working directory
+WORKDIR C:\build
+
+# Copy prepped NuGet artifacts, and restore as distinct layer to take better advantage of caching
+COPY --from=prep .\nuget .\
+RUN nuget restore
+
+# Copy remaining source code
+COPY src\ .\src\
+
+# Copy transforms, retaining directory structure
+RUN Invoke-Expression 'robocopy C:\build\src C:\out\transforms /s /ndl /njh /njs *.xdt'
+
+# Build website with file publish
+RUN msbuild .\src\src\Dianoga\Dianoga.csproj /p:Configuration=$env:BUILD_CONFIGURATION /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:PublishUrl=C:\out\website
+
+# Build XConnect with file publish
+RUN msbuild .\src\DockerExamples.XConnect\DockerExamples.XConnect.csproj /p:Configuration=$env:BUILD_CONFIGURATION /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:PublishUrl=C:\out\xconnect
+
+FROM ${BASE_IMAGE}
+
+WORKDIR C:\artifacts
+
+# Copy final build artifacts
+COPY --from=builder C:\out\website .\website\
+COPY --from=builder C:\out\transforms .\transforms\
+COPY --from=builder C:\out\xconnect .\xconnect\
\ No newline at end of file
diff --git a/integration-tests/docker-compose.override.svg.webp.avif.jxl.yml b/integration-tests/docker-compose.override.svg.webp.avif.jxl.yml
new file mode 100644
index 00000000..4fe7d612
--- /dev/null
+++ b/integration-tests/docker-compose.override.svg.webp.avif.jxl.yml
@@ -0,0 +1,123 @@
+# Compose file for Dianoga default configuration and enabled SVG & WebP & AVIF & JPEG XL optimization
+version: "2.4"
+
+services:
+ test:
+ # Same test image shared for all tests
+ # But not all tests are executed. Execution depends on passed environment variables
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-test:${VERSION:-latest}
+ build:
+ context: ./docker/build/test
+ depends_on:
+ traefik:
+ condition: service_healthy
+ volumes:
+ - ./docker/data/tests:C:/results
+ environment:
+ CDHostname: http://cd
+ TestConfigurationName: default-svg-webp-avif-jxl
+ Async: "true"
+ SvgOptimizationEnabled: "true"
+ WebpOptimizationEnabled: "true"
+ JxlOptimizationEnabled: "true"
+ AvifOptimizationEnabled: "true"
+
+ dianoga:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ build:
+ context: ../.
+ args:
+ BASE_IMAGE: ${DIANOGA_BASE_IMAGE}
+ BUILD_IMAGE: ${DIANOGA_BUILD_IMAGE}
+
+ traefik:
+ volumes:
+ - ./docker/traefik:C:/etc/traefik
+ depends_on:
+ cm:
+ condition: service_healthy
+ cd:
+ condition: service_healthy
+
+ redis:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-redis:${VERSION:-latest}
+ build:
+ context: ./docker/build/redis
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-redis:${SITECORE_VERSION}
+
+ mssql:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-mssql:${VERSION:-latest}
+ build:
+ context: ./docker/build/mssql
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ mem_limit: 2GB
+ volumes:
+ - ${LOCAL_DATA_PATH}\mssql:c:\data
+
+ # Mount our Solr data folder
+ solr:
+ volumes:
+ - ${LOCAL_DATA_PATH}\solr:c:\data
+
+ # Some modules (like SXA) also require additions to the Solr image.
+ solr-init:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-solr-init:${VERSION:-latest}
+ build:
+ context: ./docker/build/solr-init
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-solr-init:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+
+ id:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-id:${VERSION:-latest}
+ build:
+ context: ./docker/build/id
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-id:${SITECORE_VERSION}
+
+ cd:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd-async-svg-webp-avif-jxl:${VERSION:-latest}
+ build:
+ context: ./docker/build/cd-async-svg-webp-avif-jxl
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs
+ - ${LOCAL_DATA_PATH}\mediaCache:C:\inetpub\wwwroot\App_Data\mediaCache
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+ # For some Dianoga optimizers, it is necessary to have write access to the temp folder
+ # tmpfs:
+ # - C:\Windows\TEMP\
+
+ cm:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest}
+ build:
+ context: ./docker/build/cm
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
diff --git a/integration-tests/docker-compose.override.svg.webp.yml b/integration-tests/docker-compose.override.svg.webp.yml
new file mode 100644
index 00000000..6cefb23d
--- /dev/null
+++ b/integration-tests/docker-compose.override.svg.webp.yml
@@ -0,0 +1,124 @@
+#Compose file for Dianoga default configuration and enabled SVG & WebP optimization
+version: "2.4"
+
+services:
+ test:
+ # Same test image shared for all tests
+ # But not all tests are executed. Execution depends on passed environment variables
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-test:${VERSION:-latest}
+ build:
+ context: ./docker/build/test
+ depends_on:
+ traefik:
+ condition: service_healthy
+ volumes:
+ - ./docker/data/tests:C:/results
+ environment:
+ CDHostname: http://cd
+ TestConfigurationName: default-svg-webp
+ Async: "true"
+ SvgOptimizationEnabled: "true"
+ WebpOptimizationEnabled: "true"
+ JxlOptimizationEnabled: "false"
+ AvifOptimizationEnabled: "false"
+
+ dianoga:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ build:
+ context: ../.
+ args:
+ BASE_IMAGE: ${DIANOGA_BASE_IMAGE}
+ BUILD_IMAGE: ${DIANOGA_BUILD_IMAGE}
+
+ traefik:
+ volumes:
+ - ./docker/traefik:C:/etc/traefik
+ depends_on:
+ cm:
+ condition: service_healthy
+ cd:
+ condition: service_healthy
+
+ redis:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-redis:${VERSION:-latest}
+ build:
+ context: ./docker/build/redis
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-redis:${SITECORE_VERSION}
+
+ mssql:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-mssql:${VERSION:-latest}
+ build:
+ context: ./docker/build/mssql
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ mem_limit: 2GB
+ volumes:
+ - ${LOCAL_DATA_PATH}\mssql:c:\data
+
+ # Mount our Solr data folder
+ solr:
+ volumes:
+ - ${LOCAL_DATA_PATH}\solr:c:\data
+
+ # Some modules (like SXA) also require additions to the Solr image.
+ solr-init:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-solr-init:${VERSION:-latest}
+ build:
+ context: ./docker/build/solr-init
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-solr-init:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+
+ id:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-id:${VERSION:-latest}
+ build:
+ context: ./docker/build/id
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-id:${SITECORE_VERSION}
+
+ cd:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd-async-svg-webp:${VERSION:-latest}
+ build:
+ context: ./docker/build/cd-async-svg-webp
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs
+ - ${LOCAL_DATA_PATH}\mediaCache:C:\inetpub\wwwroot\App_Data\mediaCache
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
+ # For some Dianoga optimizers, it is necessary to have write access to the temp folder
+ # tmpfs:
+ # - C:\Windows\TEMP\
+
+ cm:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest}
+ build:
+ context: ./docker/build/cm
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
\ No newline at end of file
diff --git a/integration-tests/docker-compose.override.svg.yml b/integration-tests/docker-compose.override.svg.yml
new file mode 100644
index 00000000..1f16c631
--- /dev/null
+++ b/integration-tests/docker-compose.override.svg.yml
@@ -0,0 +1,126 @@
+#Compose file for Dianoga default configuration and enabled SVG optimization
+version: "2.4"
+
+services:
+ test:
+ # Same test image shared for all tests
+ # But not all tests are executed. Execution depends on passed environment variables
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-test:${VERSION:-latest}
+ build:
+ context: ./docker/build/test
+ depends_on:
+ traefik:
+ condition: service_healthy
+ volumes:
+ - ./docker/data/tests:C:/results
+ environment:
+ CDHostname: http://cd
+ TestConfigurationName: default-svg
+ Async: "true"
+ SvgOptimizationEnabled: "true"
+ WebpOptimizationEnabled: "false"
+ JxlOptimizationEnabled: "false"
+ AvifOptimizationEnabled: "false"
+
+ dianoga:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ build:
+ context: ../.
+ args:
+ BASE_IMAGE: ${DIANOGA_BASE_IMAGE}
+ BUILD_IMAGE: ${DIANOGA_BUILD_IMAGE}
+
+ traefik:
+ volumes:
+ - ./docker/traefik:C:/etc/traefik
+ depends_on:
+ cm:
+ condition: service_healthy
+ cd:
+ condition: service_healthy
+
+
+ redis:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-redis:${VERSION:-latest}
+ build:
+ context: ./docker/build/redis
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-redis:${SITECORE_VERSION}
+
+ mssql:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-mssql:${VERSION:-latest}
+ build:
+ context: ./docker/build/mssql
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ mem_limit: 2GB
+ volumes:
+ - ${LOCAL_DATA_PATH}\mssql:c:\data
+
+ # Mount our Solr data folder
+ solr:
+ volumes:
+ - ${LOCAL_DATA_PATH}\solr:c:\data
+
+ # Some modules (like SXA) also require additions to the Solr image.
+ solr-init:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-solr-init:${VERSION:-latest}
+ build:
+ context: ./docker/build/solr-init
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-solr-init:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+
+ id:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-id:${VERSION:-latest}
+ build:
+ context: ./docker/build/id
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-id:${SITECORE_VERSION}
+
+ cd:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd-async-svg:${VERSION:-latest}
+ build:
+ context: ./docker/build/cd-async-svg
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs
+ - ${LOCAL_DATA_PATH}\mediaCache:C:\inetpub\wwwroot\App_Data\mediaCache
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
+ # For some Dianoga optimizers, it is necessary to have write access to the temp folder
+ # tmpfs:
+ # - C:\Windows\TEMP\
+
+ cm:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest}
+ build:
+ context: ./docker/build/cm
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
\ No newline at end of file
diff --git a/integration-tests/docker-compose.override.sync.yml b/integration-tests/docker-compose.override.sync.yml
new file mode 100644
index 00000000..59c258ab
--- /dev/null
+++ b/integration-tests/docker-compose.override.sync.yml
@@ -0,0 +1,125 @@
+#Compose file for Dianoga default configuration with turned off async mode and turned on sync mode
+version: "2.4"
+
+services:
+ test:
+ # Same test image shared for all tests
+ # But not all tests are executed. Execution depends on passed environment variables
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-test:${VERSION:-latest}
+ build:
+ context: ./docker/build/test
+ depends_on:
+ traefik:
+ condition: service_healthy
+ volumes:
+ - ./docker/data/tests:C:/results
+ environment:
+ CDHostname: http://cd
+ TestConfigurationName: default-sync
+ Async: "false"
+ SvgOptimizationEnabled: "false"
+ WebpOptimizationEnabled: "false"
+ JxlOptimizationEnabled: "false"
+ AvifOptimizationEnabled: "false"
+
+ dianoga:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ build:
+ context: ../.
+ args:
+ BASE_IMAGE: ${DIANOGA_BASE_IMAGE}
+ BUILD_IMAGE: ${DIANOGA_BUILD_IMAGE}
+
+ traefik:
+ volumes:
+ - ./docker/traefik:C:/etc/traefik
+ depends_on:
+ cm:
+ condition: service_healthy
+ cd:
+ condition: service_healthy
+
+ redis:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-redis:${VERSION:-latest}
+ build:
+ context: ./docker/build/redis
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-redis:${SITECORE_VERSION}
+
+ mssql:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-mssql:${VERSION:-latest}
+ build:
+ context: ./docker/build/mssql
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ mem_limit: 2GB
+ volumes:
+ - ${LOCAL_DATA_PATH}\mssql:c:\data
+
+ # Mount our Solr data folder
+ solr:
+ volumes:
+ - ${LOCAL_DATA_PATH}\solr:c:\data
+
+ # Some modules (like SXA) also require additions to the Solr image.
+ solr-init:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-solr-init:${VERSION:-latest}
+ build:
+ context: ./docker/build/solr-init
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-solr-init:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+
+ id:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-id:${VERSION:-latest}
+ build:
+ context: ./docker/build/id
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-id:${SITECORE_VERSION}
+
+ cd:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd-sync:${VERSION:-latest}
+ build:
+ context: ./docker/build/cd-sync
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs
+ - ${LOCAL_DATA_PATH}\mediaCache:C:\inetpub\wwwroot\App_Data\mediaCache
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
+ # For some Dianoga optimizers, it is necessary to have write access to the temp folder
+ # tmpfs:
+ # - C:\Windows\TEMP\
+
+ cm:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest}
+ build:
+ context: ./docker/build/cm
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
\ No newline at end of file
diff --git a/integration-tests/docker-compose.override.yml b/integration-tests/docker-compose.override.yml
new file mode 100644
index 00000000..6dc3791e
--- /dev/null
+++ b/integration-tests/docker-compose.override.yml
@@ -0,0 +1,125 @@
+#Compose file for Dianoga default configuration
+
+version: "2.4"
+
+services:
+ test:
+ # Same test image shared for all tests
+ # But not all tests are executed. Execution depends on passed environment variables
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-test:${VERSION:-latest}
+ build:
+ context: ./docker/build/test
+ depends_on:
+ traefik:
+ condition: service_healthy
+ volumes:
+ - ./docker/data/tests:C:/results
+ environment:
+ CDHostname: http://cd
+ TestConfigurationName: default
+ Async: "true"
+ SvgOptimizationEnabled: "false"
+ WebpOptimizationEnabled: "false"
+ JxlOptimizationEnabled: "false"
+ AvifOptimizationEnabled: "false"
+
+ dianoga:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ build:
+ context: ../.
+ args:
+ BASE_IMAGE: ${DIANOGA_BASE_IMAGE}
+ BUILD_IMAGE: ${DIANOGA_BUILD_IMAGE}
+
+ traefik:
+ volumes:
+ - ./docker/traefik:C:/etc/traefik
+ depends_on:
+ cd:
+ condition: service_healthy
+ cm:
+ condition: service_healthy
+
+ redis:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-redis:${VERSION:-latest}
+ build:
+ context: ./docker/build/redis
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-redis:${SITECORE_VERSION}
+
+ mssql:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-mssql:${VERSION:-latest}
+ build:
+ context: ./docker/build/mssql
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ mem_limit: 2GB
+ volumes:
+ - ${LOCAL_DATA_PATH}\mssql:c:\data
+
+ # Mount our Solr data folder
+ solr:
+ volumes:
+ - ${LOCAL_DATA_PATH}\solr:c:\data
+
+ # Some modules (like SXA) also require additions to the Solr image.
+ solr-init:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-solr-init:${VERSION:-latest}
+ build:
+ context: ./docker/build/solr-init
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-solr-init:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+
+ id:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-id:${VERSION:-latest}
+ build:
+ context: ./docker/build/id
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-id:${SITECORE_VERSION}
+
+ cd:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd-async:${VERSION:-latest}
+ build:
+ context: ./docker/build/cd
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs
+ - ${LOCAL_DATA_PATH}\mediaCache:C:\inetpub\wwwroot\App_Data\mediaCache
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
+ # For some Dianoga optimizers, it is necessary to have write access to the temp folder
+ # tmpfs:
+ # - C:\Windows\TEMP\
+
+ cm:
+ image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest}
+ build:
+ context: ./docker/build/cm
+ args:
+ BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
+ SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}spe-assets:${SPE_VERSION}
+ SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sxa-xm1-assets:${SXA_VERSION}
+ TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION}
+ HORIZON_RESOURCES_IMAGE: ${SITECORE_MODULE_REGISTRY}horizon-integration-xm1-assets:${HORIZON_ASSET_VERSION}
+ DIANOGA_IMAGE: ${REGISTRY}${COMPOSE_PROJECT_NAME}-dianoga-tools:${VERSION:-latest}
+ depends_on:
+ - dianoga
+ volumes:
+ - ${LOCAL_DEPLOY_PATH}\website:C:\deploy
+ - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs
+ environment:
+ SITECORE_DEVELOPMENT_PATCHES: CustomErrorsOff
+ entrypoint: powershell -Command "& C:\tools\entrypoints\iis\Development.ps1"
+
\ No newline at end of file
diff --git a/integration-tests/docker-compose.yml b/integration-tests/docker-compose.yml
new file mode 100644
index 00000000..552cc17a
--- /dev/null
+++ b/integration-tests/docker-compose.yml
@@ -0,0 +1,156 @@
+version: "2.4"
+services:
+ traefik:
+ isolation: ${TRAEFIK_ISOLATION}
+ image: ${TRAEFIK_IMAGE}
+ command:
+ - "--ping"
+ - "--api.insecure=true"
+ - "--providers.docker.endpoint=npipe:////./pipe/docker_engine"
+ - "--providers.docker.exposedByDefault=false"
+ - "--providers.file.directory=C:/etc/traefik/config/dynamic"
+ - "--entryPoints.websecure.address=:443"
+ ports:
+ - "443:443"
+ - "8079:8080"
+ healthcheck:
+ test: ["CMD", "traefik", "healthcheck", "--ping"]
+ volumes:
+ - source: \\.\pipe\docker_engine
+ target: \\.\pipe\docker_engine
+ type: npipe
+ - ./traefik:C:/etc/traefik
+ depends_on:
+ id:
+ condition: service_healthy
+ cd:
+ condition: service_healthy
+ cm:
+ condition: service_healthy
+ redis:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}sitecore-redis:${SITECORE_VERSION}
+ mssql:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql:${SITECORE_VERSION}
+ environment:
+ SA_PASSWORD: ${SQL_SA_PASSWORD}
+ SITECORE_ADMIN_PASSWORD: ${SITECORE_ADMIN_PASSWORD}
+ ACCEPT_EULA: "Y"
+ ports:
+ - "14330:1433"
+ volumes:
+ - type: bind
+ source: .\mssql-data
+ target: c:\data
+ solr:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}nonproduction/solr:8.4.0-${SITECORE_VERSION}
+ ports:
+ - "8984:8983"
+ volumes:
+ - type: bind
+ source: .\solr-data
+ target: c:\data
+ environment:
+ SOLR_MODE: solrcloud
+ solr-init:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-solr-init:${SITECORE_VERSION}
+ environment:
+ SITECORE_SOLR_CONNECTION_STRING: http://solr:8983/solr
+ SOLR_CORE_PREFIX_NAME: ${SOLR_CORE_PREFIX_NAME}
+ depends_on:
+ solr:
+ condition: service_healthy
+ id:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}sitecore-id:${SITECORE_VERSION}
+ environment:
+ Sitecore_Sitecore__IdentityServer__SitecoreMemberShipOptions__ConnectionString: Data Source=mssql;Initial Catalog=Sitecore.Core;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_Sitecore__IdentityServer__AccountOptions__PasswordRecoveryUrl: https://${CM_HOST}/sitecore/login?rc=1
+ Sitecore_Sitecore__IdentityServer__Clients__PasswordClient__ClientSecrets__ClientSecret1: ${SITECORE_IDSECRET}
+ Sitecore_Sitecore__IdentityServer__Clients__DefaultClient__AllowedCorsOrigins__AllowedCorsOriginsGroup1: https://${CM_HOST}
+ Sitecore_Sitecore__IdentityServer__CertificateRawData: ${SITECORE_ID_CERTIFICATE}
+ Sitecore_Sitecore__IdentityServer__PublicOrigin: https://${ID_HOST}
+ Sitecore_Sitecore__IdentityServer__CertificateRawDataPassword: ${SITECORE_ID_CERTIFICATE_PASSWORD}
+ Sitecore_License: ${SITECORE_LICENSE}
+ healthcheck:
+ test: ["CMD", "powershell", "-command", "C:/Healthchecks/Healthcheck.ps1"]
+ timeout: 300s
+ depends_on:
+ mssql:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.id-secure.entrypoints=websecure"
+ - "traefik.http.routers.id-secure.rule=Host(`${ID_HOST}`)"
+ - "traefik.http.routers.id-secure.tls=true"
+ cd:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION}
+ depends_on:
+ mssql:
+ condition: service_healthy
+ solr-init:
+ condition: service_started
+ redis:
+ condition: service_started
+ environment:
+ Sitecore_AppSettings_instanceNameMode:define: default
+ Sitecore_ConnectionStrings_Security: Data Source=mssql;Initial Catalog=Sitecore.Core;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_Web: Data Source=mssql;Initial Catalog=Sitecore.Web;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_ExperienceForms: Data Source=mssql;Initial Catalog=Sitecore.ExperienceForms;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_Solr.Search: http://solr:8983/solr;solrCloud=true
+ Sitecore_ConnectionStrings_Redis.Sessions: redis:6379,ssl=False,abortConnect=False
+ Sitecore_License: ${SITECORE_LICENSE}
+ SOLR_CORE_PREFIX_NAME: ${SOLR_CORE_PREFIX_NAME}
+ MEDIA_REQUEST_PROTECTION_SHARED_SECRET: ${MEDIA_REQUEST_PROTECTION_SHARED_SECRET}
+ healthcheck:
+ test: ["CMD", "powershell", "-command", "C:/Healthchecks/Healthcheck.ps1"]
+ timeout: 300s
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.cd-secure.entrypoints=websecure"
+ - "traefik.http.routers.cd-secure.rule=Host(`${CD_HOST}`)"
+ - "traefik.http.routers.cd-secure.tls=true"
+ cm:
+ isolation: ${ISOLATION}
+ image: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
+ depends_on:
+ mssql:
+ condition: service_healthy
+ solr-init:
+ condition: service_started
+ id:
+ condition: service_started
+ environment:
+ Sitecore_AppSettings_instanceNameMode:define: default
+ Sitecore_ConnectionStrings_Core: Data Source=mssql;Initial Catalog=Sitecore.Core;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_Security: Data Source=mssql;Initial Catalog=Sitecore.Core;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_Master: Data Source=mssql;Initial Catalog=Sitecore.Master;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_Web: Data Source=mssql;Initial Catalog=Sitecore.Web;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_ExperienceForms: Data Source=mssql;Initial Catalog=Sitecore.ExperienceForms;User ID=sa;Password=${SQL_SA_PASSWORD}
+ Sitecore_ConnectionStrings_Solr.Search: http://solr:8983/solr;solrCloud=true
+ Sitecore_ConnectionStrings_Sitecoreidentity.secret: ${SITECORE_IDSECRET}
+ Sitecore_AppSettings_Telerik.AsyncUpload.ConfigurationEncryptionKey: ${TELERIK_ENCRYPTION_KEY}
+ Sitecore_AppSettings_Telerik.Upload.ConfigurationHashKey: ${TELERIK_ENCRYPTION_KEY}
+ Sitecore_AppSettings_Telerik.Web.UI.DialogParametersEncryptionKey: ${TELERIK_ENCRYPTION_KEY}
+ Sitecore_License: ${SITECORE_LICENSE}
+ Sitecore_Identity_Server_Authority: https://${ID_HOST}
+ Sitecore_Identity_Server_InternalAuthority: http://id
+ Sitecore_Identity_Server_CallbackAuthority: https://${CM_HOST}
+ Sitecore_Identity_Server_Require_Https: "false"
+ SOLR_CORE_PREFIX_NAME: ${SOLR_CORE_PREFIX_NAME}
+ MEDIA_REQUEST_PROTECTION_SHARED_SECRET: ${MEDIA_REQUEST_PROTECTION_SHARED_SECRET}
+ healthcheck:
+ test: ["CMD", "powershell", "-command", "C:/Healthchecks/Healthcheck.ps1"]
+ timeout: 300s
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.middlewares.force-STS-Header.headers.forceSTSHeader=true"
+ - "traefik.http.middlewares.force-STS-Header.headers.stsSeconds=31536000"
+ - "traefik.http.routers.cm-secure.entrypoints=websecure"
+ - "traefik.http.routers.cm-secure.rule=Host(`${CM_HOST}`)"
+ - "traefik.http.routers.cm-secure.tls=true"
+ - "traefik.http.routers.cm-secure.middlewares=force-STS-Header"
diff --git a/integration-tests/docker/.gitignore b/integration-tests/docker/.gitignore
new file mode 100644
index 00000000..297b352d
--- /dev/null
+++ b/integration-tests/docker/.gitignore
@@ -0,0 +1,16 @@
+/data/cm/*
+!/data/cm/.gitkeep
+/data/cd/*
+!/data/cd/.gitkeep
+/data/mssql/*
+!/data/mssql/.gitkeep
+/data/solr/*
+!/data/solr/.gitkeep
+
+/deploy/website/*
+!/deploy/website/.gitkeep
+/deploy/xconnect/*
+!/deploy/xconnect/.gitkeep
+
+/traefik/certs/*
+!/traefik/certs/.gitkeep
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd-async-svg-webp-avif-jxl/Dockerfile b/integration-tests/docker/build/cd-async-svg-webp-avif-jxl/Dockerfile
new file mode 100644
index 00000000..088b3f4f
--- /dev/null
+++ b/integration-tests/docker/build/cd-async-svg-webp-avif-jxl/Dockerfile
@@ -0,0 +1,47 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG TOOLING_IMAGE
+ARG DIANOGA_IMAGE
+
+FROM ${TOOLING_IMAGE} as tooling
+FROM ${SXA_IMAGE} as sxa
+FROM ${DIANOGA_IMAGE} as dianoga
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Copy development tools and entrypoint
+COPY --from=tooling \tools\ \tools\
+
+WORKDIR C:\inetpub\wwwroot
+
+# Add SXA module
+COPY --from=sxa \module\cd\content .\
+COPY --from=sxa \module\tools \module\tools
+RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; `
+ Remove-Item -Path C:\module -Recurse -Force;
+
+# Add Dianoga module
+# Install Microsoft Visual C++ Runtime, because image tools(e.g. pngquant.exe, avifenc.exe) depends on it.
+# Probably, less generic Visual C++ Runtime will be OK.
+RUN Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+RUN choco install vcredist-all -y
+COPY --from=dianoga \module\cd\content .\
+
+# Enable SVG optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\Dianoga.Svg.config.disabled -NewName Dianoga.Svg.config
+# Enable WebP optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\z.01.Dianoga.NextGenFormats.WebP.config.disabled -NewName z.01.Dianoga.NextGenFormats.WebP.config
+# Enable AVIF optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\z.02.Dianoga.NextGenFormats.Avif.config.disabled -NewName z.02.Dianoga.NextGenFormats.Avif.config.config
+# Enable JXL optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\z.03.Dianoga.NextGenFormats.JpegXL.config.disabled -NewName z.03.Dianoga.NextGenFormats.JpegXL.config
+
+# Change default Media Request Handler to be able to use NextGenFormats
+COPY Web.config.xdt ./Web.config.Dianoga.xdt
+RUN Powershell C:\tools\scripts\Invoke-XdtTransform.ps1 -Path Web.config -XdtPath Web.config.Dianoga.xdt
+
+# Disable Media Request Protection for simplicity of testing (no need to worry about hash get parameter)
+RUN Powershell Rename-Item -Path "C:\inetpub\wwwroot\App_Config\Sitecore\CMS.Core\Sitecore.Media.RequestProtection.config" -NewName "Sitecore.Media.RequestProtection.config.disabled"
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd-async-svg-webp-avif-jxl/Web.config.xdt b/integration-tests/docker/build/cd-async-svg-webp-avif-jxl/Web.config.xdt
new file mode 100644
index 00000000..d67f7eab
--- /dev/null
+++ b/integration-tests/docker/build/cd-async-svg-webp-avif-jxl/Web.config.xdt
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd-async-svg-webp/Dockerfile b/integration-tests/docker/build/cd-async-svg-webp/Dockerfile
new file mode 100644
index 00000000..9d9ed183
--- /dev/null
+++ b/integration-tests/docker/build/cd-async-svg-webp/Dockerfile
@@ -0,0 +1,42 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG TOOLING_IMAGE
+ARG DIANOGA_IMAGE
+
+FROM ${TOOLING_IMAGE} as tooling
+FROM ${SXA_IMAGE} as sxa
+FROM ${DIANOGA_IMAGE} as dianoga
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Copy development tools and entrypoint
+COPY --from=tooling \tools\ \tools\
+
+WORKDIR C:\inetpub\wwwroot
+
+# Add SXA module
+COPY --from=sxa \module\cd\content .\
+COPY --from=sxa \module\tools \module\tools
+RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; `
+ Remove-Item -Path C:\module -Recurse -Force;
+
+# Add Dianoga module
+# Install Microsoft Visual C++ Runtime, because image tools(e.g. pngquant.exe, avifenc.exe) depends on it.
+# Probably, less generic Visual C++ Runtime will be OK.
+RUN Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+RUN choco install vcredist-all -y
+COPY --from=dianoga \module\cd\content .\
+
+# Enable SVG optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\Dianoga.Svg.config.disabled -NewName Dianoga.Svg.config
+# Enable WebP optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\z.01.Dianoga.NextGenFormats.WebP.config.disabled -NewName z.01.Dianoga.NextGenFormats.WebP.config
+# Change default Media Request Handler to be able to use NextGenFormats
+COPY Web.config.xdt ./Web.config.Dianoga.xdt
+RUN Powershell C:\tools\scripts\Invoke-XdtTransform.ps1 -Path Web.config -XdtPath Web.config.Dianoga.xdt
+
+# Disable Media Request Protection for simplicity of testing (no need to worry about hash get parameter)
+RUN Powershell Rename-Item -Path "C:\inetpub\wwwroot\App_Config\Sitecore\CMS.Core\Sitecore.Media.RequestProtection.config" -NewName "Sitecore.Media.RequestProtection.config.disabled"
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd-async-svg-webp/Web.config.xdt b/integration-tests/docker/build/cd-async-svg-webp/Web.config.xdt
new file mode 100644
index 00000000..d67f7eab
--- /dev/null
+++ b/integration-tests/docker/build/cd-async-svg-webp/Web.config.xdt
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd-async-svg/Dockerfile b/integration-tests/docker/build/cd-async-svg/Dockerfile
new file mode 100644
index 00000000..d9754835
--- /dev/null
+++ b/integration-tests/docker/build/cd-async-svg/Dockerfile
@@ -0,0 +1,37 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG TOOLING_IMAGE
+ARG DIANOGA_IMAGE
+
+FROM ${TOOLING_IMAGE} as tooling
+FROM ${SXA_IMAGE} as sxa
+FROM ${DIANOGA_IMAGE} as dianoga
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Copy development tools and entrypoint
+COPY --from=tooling \tools\ \tools\
+
+WORKDIR C:\inetpub\wwwroot
+
+# Add Dianoga module
+# Install Microsoft Visual C++ Runtime, because image tools(e.g. pngquant.exe, avifenc.exe) depends on it.
+# Probably, less generic Visual C++ Runtime will be OK.
+RUN Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+RUN choco install vcredist-all -y
+COPY --from=dianoga \module\cd\content .\
+
+# Enable SVG optimization
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\Dianoga.Svg.config.disabled -NewName Dianoga.Svg.config
+
+# Add SXA module
+COPY --from=sxa \module\cd\content .\
+COPY --from=sxa \module\tools \module\tools
+RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; `
+ Remove-Item -Path C:\module -Recurse -Force;
+
+# Disable Media Request Protection for simplicity of testing (no need to worry about hash get parameter)
+RUN Powershell Rename-Item -Path "C:\inetpub\wwwroot\App_Config\Sitecore\CMS.Core\Sitecore.Media.RequestProtection.config" -NewName "Sitecore.Media.RequestProtection.config.disabled"
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd-sync/Dockerfile b/integration-tests/docker/build/cd-sync/Dockerfile
new file mode 100644
index 00000000..b6078eb0
--- /dev/null
+++ b/integration-tests/docker/build/cd-sync/Dockerfile
@@ -0,0 +1,39 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG TOOLING_IMAGE
+ARG DIANOGA_IMAGE
+
+FROM ${TOOLING_IMAGE} as tooling
+FROM ${SXA_IMAGE} as sxa
+FROM ${DIANOGA_IMAGE} as dianoga
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Copy development tools and entrypoint
+COPY --from=tooling \tools\ \tools\
+
+WORKDIR C:\inetpub\wwwroot
+
+# Add Dianoga module
+# Install Microsoft Visual C++ Runtime, because image tools(e.g. pngquant.exe, avifenc.exe) depends on it.
+# Probably, less generic Visual C++ Runtime will be OK.
+RUN Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+RUN choco install vcredist-all -y
+COPY --from=dianoga \module\cd\content .\
+
+# Turn on Sync mode
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\Dianoga.Strategy.GetMediaStreamSync.config.disabled -NewName Dianoga.Strategy.GetMediaStreamSync.config
+# Turn off Async mode
+RUN Rename-Item -Path C:\inetpub\wwwroot\App_Config\Include\Dianoga\Dianoga.Strategy.MediaCacheAsync.config -NewName Dianoga.Strategy.MediaCacheAsync.config.disabled
+
+# Add SXA module
+COPY --from=sxa \module\cd\content .\
+COPY --from=sxa \module\tools \module\tools
+RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; `
+ Remove-Item -Path C:\module -Recurse -Force;
+
+# Disable Media Request Protection for simplicity of testing (no need to worry about hash get parameter)
+RUN Powershell Rename-Item -Path "C:\inetpub\wwwroot\App_Config\Sitecore\CMS.Core\Sitecore.Media.RequestProtection.config" -NewName "Sitecore.Media.RequestProtection.config.disabled"
\ No newline at end of file
diff --git a/integration-tests/docker/build/cd/Dockerfile b/integration-tests/docker/build/cd/Dockerfile
new file mode 100644
index 00000000..1d5f6d60
--- /dev/null
+++ b/integration-tests/docker/build/cd/Dockerfile
@@ -0,0 +1,34 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG TOOLING_IMAGE
+ARG DIANOGA_IMAGE
+
+FROM ${TOOLING_IMAGE} as tooling
+FROM ${SXA_IMAGE} as sxa
+FROM ${DIANOGA_IMAGE} as dianoga
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Copy development tools and entrypoint
+COPY --from=tooling \tools\ \tools\
+
+WORKDIR C:\inetpub\wwwroot
+
+# Add Dianoga module
+# Install Microsoft Visual C++ Runtime, because image tools(e.g. pngquant.exe, avifenc.exe) depends on it.
+# Probably, less generic Visual C++ Runtime will be OK.
+RUN Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+RUN choco install vcredist-all -y
+COPY --from=dianoga \module\cd\content .\
+
+# Add SXA module
+COPY --from=sxa \module\cd\content .\
+COPY --from=sxa \module\tools \module\tools
+RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; `
+ Remove-Item -Path C:\module -Recurse -Force;
+
+# Disable Media Request Protection for simplicity of testing (no need to worry about hash get parameter)
+RUN Powershell Rename-Item -Path "C:\inetpub\wwwroot\App_Config\Sitecore\CMS.Core\Sitecore.Media.RequestProtection.config" -NewName "Sitecore.Media.RequestProtection.config.disabled"
\ No newline at end of file
diff --git a/integration-tests/docker/build/cm/Dockerfile b/integration-tests/docker/build/cm/Dockerfile
new file mode 100644
index 00000000..ca814deb
--- /dev/null
+++ b/integration-tests/docker/build/cm/Dockerfile
@@ -0,0 +1,41 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG SPE_IMAGE
+ARG TOOLING_IMAGE
+ARG DIANOGA_IMAGE
+
+FROM ${TOOLING_IMAGE} as tooling
+FROM ${SPE_IMAGE} as spe
+FROM ${SXA_IMAGE} as sxa
+FROM ${DIANOGA_IMAGE} as dianoga
+FROM ${BASE_IMAGE}
+
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+
+
+# Copy development tools and entrypoint
+COPY --from=tooling \tools\ \tools\
+
+WORKDIR C:\inetpub\wwwroot
+
+# Add Dianoga module
+
+#RUN Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+#RUN choco install vcredist-all -y
+#COPY --from=dianoga \module\cd\content .\
+
+# Add SPE module
+COPY --from=spe \module\cm\content .\
+
+# Add SXA module
+COPY --from=sxa \module\cm\content .\
+COPY --from=sxa \module\tools \module\tools
+RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; `
+ Remove-Item -Path C:\module -Recurse -Force;
+
+# Disable Media Request Protection for simplicity of testing (no need to worry about hash get parameter)
+RUN Powershell Rename-Item -Path "C:\inetpub\wwwroot\App_Config\Sitecore\CMS.Core\Sitecore.Media.RequestProtection.config" -NewName "Sitecore.Media.RequestProtection.config.disabled"
\ No newline at end of file
diff --git a/integration-tests/docker/build/cm/transforms/Web.config.xdt b/integration-tests/docker/build/cm/transforms/Web.config.xdt
new file mode 100644
index 00000000..4f5567c2
--- /dev/null
+++ b/integration-tests/docker/build/cm/transforms/Web.config.xdt
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/docker/build/id/Dockerfile b/integration-tests/docker/build/id/Dockerfile
new file mode 100644
index 00000000..86bba36d
--- /dev/null
+++ b/integration-tests/docker/build/id/Dockerfile
@@ -0,0 +1,5 @@
+# escape=`
+
+ARG BASE_IMAGE
+
+FROM ${BASE_IMAGE}
\ No newline at end of file
diff --git a/integration-tests/docker/build/mssql/Dockerfile b/integration-tests/docker/build/mssql/Dockerfile
new file mode 100644
index 00000000..500648fd
--- /dev/null
+++ b/integration-tests/docker/build/mssql/Dockerfile
@@ -0,0 +1,29 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+ARG SPE_IMAGE
+
+FROM ${SPE_IMAGE} as spe
+FROM ${SXA_IMAGE} as sxa
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Add SPE module
+COPY --from=spe \module\db \spe_data
+RUN C:\DeployDatabases.ps1 -ResourcesDirectory C:\spe_data; `
+ Remove-Item -Path C:\spe_data -Recurse -Force;
+
+# Add SXA module
+COPY --from=sxa \module\db \sxa_data
+COPY --from=sxa \module\db\Sitecore.master.dacpac \sxa_data\Sitecore.web.dacpac
+RUN C:\DeployDatabases.ps1 -ResourcesDirectory C:\sxa_data; `
+ Remove-Item -Path C:\sxa_data -Recurse -Force;
+
+# Add Test data (pages and images to Web and Master databases)
+COPY Sitecore.master.dacpac \test_data\Sitecore.master.dacpac
+COPY Sitecore.master.dacpac \test_data\Sitecore.web.dacpac
+
+RUN C:\DeployDatabases.ps1 -ResourcesDirectory C:\test_data; `
+ Remove-Item -Path C:\test_data -Recurse -Force;
\ No newline at end of file
diff --git a/integration-tests/docker/build/mssql/Sitecore.master.dacpac b/integration-tests/docker/build/mssql/Sitecore.master.dacpac
new file mode 100644
index 00000000..a8fa6dd4
Binary files /dev/null and b/integration-tests/docker/build/mssql/Sitecore.master.dacpac differ
diff --git a/integration-tests/docker/build/redis/Dockerfile b/integration-tests/docker/build/redis/Dockerfile
new file mode 100644
index 00000000..86bba36d
--- /dev/null
+++ b/integration-tests/docker/build/redis/Dockerfile
@@ -0,0 +1,5 @@
+# escape=`
+
+ARG BASE_IMAGE
+
+FROM ${BASE_IMAGE}
\ No newline at end of file
diff --git a/integration-tests/docker/build/solr-init/Dockerfile b/integration-tests/docker/build/solr-init/Dockerfile
new file mode 100644
index 00000000..42c10a71
--- /dev/null
+++ b/integration-tests/docker/build/solr-init/Dockerfile
@@ -0,0 +1,12 @@
+# escape=`
+
+ARG BASE_IMAGE
+ARG SXA_IMAGE
+
+FROM ${SXA_IMAGE} as sxa
+FROM ${BASE_IMAGE}
+
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+# Add SXA module
+COPY --from=sxa C:\module\solr\cores-sxa.json C:\data\cores-sxa.json
\ No newline at end of file
diff --git a/integration-tests/docker/build/test/Results/.gitkeep b/integration-tests/docker/build/test/Results/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/build/test/dockerfile b/integration-tests/docker/build/test/dockerfile
new file mode 100644
index 00000000..d1074757
--- /dev/null
+++ b/integration-tests/docker/build/test/dockerfile
@@ -0,0 +1,14 @@
+# escape=`
+ARG BASE_IMAGE=mcr.microsoft.com/dotnet/framework/sdk:4.8
+FROM ${BASE_IMAGE}
+
+WORKDIR /
+
+COPY src\IntegrationTests\Integration ./Tests
+RUN mkdir Results
+
+WORKDIR c:\Tests
+RUN dotnet build ./Integration.csproj
+
+WORKDIR c:\Tests
+ENTRYPOINT ["powershell.exe", "-File", "test.ps1"]
\ No newline at end of file
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/.gitignore b/integration-tests/docker/build/test/src/IntegrationTests/Integration/.gitignore
new file mode 100644
index 00000000..8d4a6c08
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/.gitignore
@@ -0,0 +1,2 @@
+bin
+obj
\ No newline at end of file
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/BaseTests.cs b/integration-tests/docker/build/test/src/IntegrationTests/Integration/BaseTests.cs
new file mode 100644
index 00000000..0fc93c8e
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/BaseTests.cs
@@ -0,0 +1,61 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using Microsoft.Extensions.Configuration;
+
+namespace Integration
+{
+ public class BaseTests
+ {
+ protected string CDHostname;
+ protected bool SvgOptimizationEnabled;
+ protected bool WebpOptimizationEnabled;
+ protected bool AvifOptimizationEnabled;
+ protected bool JxlOptimizationEnabled;
+
+ protected bool Async;
+
+ protected bool Sync => !Async;
+
+ protected IConfigurationRoot ConfigurationRoot;
+
+ public BaseTests()
+ {
+ var config = new ConfigurationBuilder()
+ .AddJsonFile("appsettings.json")
+ .AddEnvironmentVariables()
+ .Build();
+
+ ConfigurationRoot = config;
+
+ CDHostname = GetStringSetting(Constants.Variables.CDHostname);
+ SvgOptimizationEnabled = GetBoolValue(Constants.Variables.SvgOptimizationEnabled);
+ WebpOptimizationEnabled = GetBoolValue(Constants.Variables.WebpOptimizationEnabled);
+ JxlOptimizationEnabled = GetBoolValue(Constants.Variables.JxlOptimizationEnabled);
+ AvifOptimizationEnabled = GetBoolValue(Constants.Variables.AvifOptimizationEnabled);
+ Async = GetBoolValue(Constants.Variables.Async);
+ }
+
+ protected string GetStringSetting(string name)
+ {
+ return Environment.GetEnvironmentVariable(name)
+ ?? ConfigurationRoot.GetValue(name);
+ }
+
+ protected bool GetBoolValue(string name)
+ {
+ var val = Environment.GetEnvironmentVariable(name);
+ return !string.IsNullOrEmpty(val)
+ ? bool.Parse(val)
+ : ConfigurationRoot.GetValue(name);
+ }
+
+ protected string ResponseToString(WebResponse response)
+ {
+ var receiveStream = response.GetResponseStream();
+ var readStream = new StreamReader(receiveStream, Encoding.UTF8);
+ return readStream.ReadToEnd();
+ }
+ }
+}
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/Constants.cs b/integration-tests/docker/build/test/src/IntegrationTests/Integration/Constants.cs
new file mode 100644
index 00000000..ffbe222f
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/Constants.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Integration
+{
+ public static class Constants
+ {
+ public static class Variables
+ {
+ public const string CDHostname = "CDHostname";
+ public const string SvgOptimizationEnabled = "SvgOptimizationEnabled";
+ public const string WebpOptimizationEnabled = "WebpOptimizationEnabled";
+ public const string AvifOptimizationEnabled = "AvifOptimizationEnabled";
+ public const string JxlOptimizationEnabled = "JxlOptimizationEnabled";
+ public const string Async = "Async";
+ }
+ }
+}
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/FileSizeTests.cs b/integration-tests/docker/build/test/src/IntegrationTests/Integration/FileSizeTests.cs
new file mode 100644
index 00000000..a0e1986f
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/FileSizeTests.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Drawing;
+using System.Net;
+using System.Net.Cache;
+using System.Threading;
+using Endjin.Retry.Async;
+using Endjin.Retry.Contracts;
+using FluentAssertions;
+using Xunit;
+
+namespace Integration
+{
+ public class FileSizeTests : BaseTests
+ {
+ [Theory]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg00.jpg", 4427080)]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg01.jpg", 4822280)]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg02.jpg", 2261738)]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg03.jpg", 5684535)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg04.jpg", 3274103)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg05.jpg", 5652302)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg06.jpg", 5220868)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg07.jpg", 1403617)]
+ public void JpegSizeTest(string url, int size)
+ {
+ SizeTest(url, size, "Dianoga should squeeze JPEG image");
+ }
+
+ [Theory]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png00.png", 100825)]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png01.png", 277679)]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png02.png", 250645)]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png03.png", 110259)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png04.png", 114270)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png05.png", 56132)]
+ public void PngSizeTest(string url, int size)
+ {
+ SizeTest(url, size, "Dianoga should squeeze PNG image");
+ }
+
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/svg/svg00.svg", 7489)]
+ [InlineData("/-/media/Project/Dianoga/Test/svg/svg01.svg", 26820)]
+ [InlineData("/-/media/Project/Dianoga/Test/svg/svg02.svg", 42147)]
+ [InlineData("/-/media/Project/Dianoga/Test/svg/svg03.svg", 161298)]
+ //[InlineData("/-/media/Project/Dianoga/Test/svg/svg04.svg", 94252)]
+ //[InlineData("/-/media/Project/Dianoga/Test/svg/svg05.svg", 48000)]
+ public void SvgSizeTest(string url, int size)
+ {
+ Skip.IfNot(SvgOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze SVG image");
+ }
+
+ public void SizeTest(string url, int size, string message)
+ {
+ var rand = new Random(DateTime.Now.Millisecond);
+ var seed = $"?seed={rand.Next(Int32.MaxValue)}";
+ var sleepService = new SleepService();
+ if (Sync)
+ {
+ var request = WebRequest.Create(CDHostname + url + seed);
+ request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
+ var response = request.GetResponse();
+ var length = response.ContentLength;
+ length.Should().BeLessThan(size, message);
+ }
+ else
+ {
+ var request = WebRequest.Create(CDHostname + url + seed);
+ request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
+ var response = request.GetResponse();
+ var string1 = ResponseToString(response);
+ var initialSize = response.ContentLength;
+ initialSize.Should().Be(size, "Original size doesn't match");
+
+ //How to find proper value, how much time file conversion will take?
+ sleepService.Sleep(new TimeSpan(0, 0, 20));
+
+ request = WebRequest.Create(CDHostname + url + seed);
+ request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
+ response = request.GetResponse();
+ var string2 = ResponseToString(response);
+ var squeezeSize = response.ContentLength;
+ squeezeSize.Should().BeLessThan(size, message);
+ }
+ }
+ }
+}
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/Integration.csproj b/integration-tests/docker/build/test/src/IntegrationTests/Integration/Integration.csproj
new file mode 100644
index 00000000..38f90ced
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/Integration.csproj
@@ -0,0 +1,35 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+ Always
+
+
+
+
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/NextGenTests.cs b/integration-tests/docker/build/test/src/IntegrationTests/Integration/NextGenTests.cs
new file mode 100644
index 00000000..6abe5a06
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/NextGenTests.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Cache;
+using System.Text;
+using Endjin.Retry.Async;
+using FluentAssertions;
+using Xunit;
+
+namespace Integration
+{
+ public class NextGenTests : BaseTests
+ {
+ /* JPEG XL shows very bad results on PNG images
+ Test fails, it is not recomended to turn it on for PNG on 2022/02/12
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png00.png", 100825)]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png01.png", 277679)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png02.png", 250645)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png03.png", 110259)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png04.png", 114270)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png05.png", 56132)]
+ public void PngJxlTest(string url, int size)
+ {
+ Skip.IfNot(JxlOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze PNG image", "image/jxl", "ftypjxl", 20);
+ }*/
+
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg00.jpg", 4427080)]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg01.jpg", 4822280)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg02.jpg", 2261738)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg03.jpg", 5684535)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg04.jpg", 3274103)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg05.jpg", 5652302)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg06.jpg", 5220868)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg07.jpg", 5220868)]
+ public void JpegJxlTest(string url, int size)
+ {
+ Skip.IfNot(JxlOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze JPEG image", "image/jxl", "ftypjxl", 30);
+ }
+
+
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png00.png", 100825)]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png01.png", 277679)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png02.png", 250645)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png03.png", 110259)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png04.png", 114270)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png05.png", 56132)]
+ public void PngAvifTest(string url, int size)
+ {
+ Skip.IfNot(AvifOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze PNG image", "image/avif", "avif");
+ }
+
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg00.jpg", 4427080)]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg01.jpg", 4822280)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg02.jpg", 2261738)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg03.jpg", 5684535)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg04.jpg", 3274103)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg05.jpg", 5652302)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg06.jpg", 5220868)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg07.jpg", 1403617)]
+ public void JpegAvifTest(string url, int size)
+ {
+ Skip.IfNot(AvifOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze JPEG image", "image/avif", "avif");
+ }
+
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png00.png", 100825)]
+ [InlineData("/-/media/Project/Dianoga/Test/png/png01.png", 277679)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png02.png", 250645)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png03.png", 110259)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png04.png", 114270)]
+ //[InlineData("/-/media/Project/Dianoga/Test/png/png05.png", 56132)]
+ public void PngWebpTest(string url, int size)
+ {
+ Skip.IfNot(WebpOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze PNG image", "image/webp", "WEBP");
+ }
+
+ [SkippableTheory]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg00.jpg", 4427080)]
+ [InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg01.jpg", 4822280)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg02.jpg", 2261738)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg03.jpg", 5684535)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg04.jpg", 3274103)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg05.jpg", 5652302)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg06.jpg", 5220868)]
+ //[InlineData("/-/media/Project/Dianoga/Test/jpeg/jpg07.jpg", 1403617)]
+ public void JpegWebpTest(string url, int size)
+ {
+ Skip.IfNot(WebpOptimizationEnabled);
+ SizeTest(url, size, "Dianoga should squeeze JPEG image", "image/webp", "WEBP");
+ }
+ public void SizeTest(string url, int size, string message, string accept, string content, int conversionTimeout = 20)
+ {
+ var rand = new Random(DateTime.Now.Millisecond);
+ var seed = $"?seed={rand.Next(Int32.MaxValue)}";
+ var sleepService = new SleepService();
+ if (Sync)
+ {
+ var request = WebRequest.Create(CDHostname + url + seed);
+ request.Headers = GetHeaders(accept);
+ request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
+ var response = request.GetResponse();
+ var string1 = ResponseToString(response);
+ var length = response.ContentLength;
+ length.Should().BeLessThan(size, message);
+ string1.IndexOf(content).Should().BeGreaterThan(-1);
+ }
+ else
+ {
+ var request = WebRequest.Create(CDHostname + url + seed);
+ request.Headers = GetHeaders(accept);
+ request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
+ var response = request.GetResponse();
+ var string1 = ResponseToString(response);
+ var initialSize = response.ContentLength;
+ string1.IndexOf(content, StringComparison.Ordinal).Should().Be(-1);
+ //How to find proper value, how much time file conversion will take?
+ sleepService.Sleep(new TimeSpan(0, 0, conversionTimeout));
+
+ request = WebRequest.Create(CDHostname + url + seed);
+ request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
+ request.Headers = GetHeaders(accept);
+ response = request.GetResponse();
+ var string2 = ResponseToString(response);
+ var squeezeSize = response.ContentLength;
+ squeezeSize.Should().BeLessThan(initialSize, message);
+ squeezeSize.Should().BeLessThan(size, message);
+ string2.IndexOf(content, StringComparison.Ordinal).Should().BeGreaterThan(-1);
+ }
+ }
+
+
+
+ private WebHeaderCollection GetHeaders(string accept)
+ {
+ var headers = new WebHeaderCollection();
+ headers.Add(HttpRequestHeader.Accept, accept);
+ return headers;
+ }
+ }
+}
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/appsettings.json b/integration-tests/docker/build/test/src/IntegrationTests/Integration/appsettings.json
new file mode 100644
index 00000000..1832fc2e
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "CDHostname": "https://cd.dockerexamples.localhost/",
+ "SvgOptimizationEnabled": true,
+ "WebpOptimizationEnabled": true,
+ "JxlOptimizationEnabled": true,
+ "AvifOptimizationEnabled": true,
+ "Async": true
+}
\ No newline at end of file
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/Integration/test.ps1 b/integration-tests/docker/build/test/src/IntegrationTests/Integration/test.ps1
new file mode 100644
index 00000000..71238434
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/Integration/test.ps1
@@ -0,0 +1,9 @@
+$datetime = Get-Date -Format "yyyyMMdd-HHmmss"
+$prefix = $env:TestConfigurationName
+$suffix = ".txt"
+$fileName = $prefix + "_" + $datetime + $suffix
+
+Write-Host $env:CDHostname
+Write-Host $env:TestConfigurationName
+
+dotnet test Integration.csproj > ..\..\results\$fileName
\ No newline at end of file
diff --git a/integration-tests/docker/build/test/src/IntegrationTests/IntegrationTests.sln b/integration-tests/docker/build/test/src/IntegrationTests/IntegrationTests.sln
new file mode 100644
index 00000000..ce936b25
--- /dev/null
+++ b/integration-tests/docker/build/test/src/IntegrationTests/IntegrationTests.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31702.278
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration", "Integration\Integration.csproj", "{90DE4F82-6FDC-486D-911D-A8B17D7FD07A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {90DE4F82-6FDC-486D-911D-A8B17D7FD07A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90DE4F82-6FDC-486D-911D-A8B17D7FD07A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90DE4F82-6FDC-486D-911D-A8B17D7FD07A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90DE4F82-6FDC-486D-911D-A8B17D7FD07A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {69A1133C-B081-4041-995D-A0A55252DEF8}
+ EndGlobalSection
+EndGlobal
diff --git a/integration-tests/docker/clean.ps1 b/integration-tests/docker/clean.ps1
new file mode 100644
index 00000000..4645a395
--- /dev/null
+++ b/integration-tests/docker/clean.ps1
@@ -0,0 +1,13 @@
+# Clean data folders
+Get-ChildItem -Path (Join-Path $PSScriptRoot "\data") -Directory | ForEach-Object {
+ $dataPath = $_.FullName
+
+ Get-ChildItem -Path $dataPath -Exclude ".gitkeep" -Recurse | Remove-Item -Force -Recurse -Verbose
+}
+
+# Clean deploy folders
+Get-ChildItem -Path (Join-Path $PSScriptRoot "\deploy") -Directory | ForEach-Object {
+ $deployPath = $_.FullName
+
+ Get-ChildItem -Path $deployPath -Exclude ".gitkeep" -Recurse | Remove-Item -Force -Recurse -Verbose
+}
\ No newline at end of file
diff --git a/integration-tests/docker/data/mediaCache/.gitkeep b/integration-tests/docker/data/mediaCache/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/data/solr/.gitkeep b/integration-tests/docker/data/solr/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/data/tests/.gitkeep b/integration-tests/docker/data/tests/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/deploy/website/.gitkeep b/integration-tests/docker/deploy/website/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/deploy/xconnect/.gitkeep b/integration-tests/docker/deploy/xconnect/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/traefik/certs/.gitkeep b/integration-tests/docker/traefik/certs/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/integration-tests/docker/traefik/config/dynamic/certs_config.yaml b/integration-tests/docker/traefik/config/dynamic/certs_config.yaml
new file mode 100644
index 00000000..4234a452
--- /dev/null
+++ b/integration-tests/docker/traefik/config/dynamic/certs_config.yaml
@@ -0,0 +1,4 @@
+tls:
+ certificates:
+ - certFile: C:\etc\traefik\certs\cert.pem
+ keyFile: C:\etc\traefik\certs\key.pem
\ No newline at end of file
diff --git a/integration-tests/init.ps1 b/integration-tests/init.ps1
new file mode 100644
index 00000000..e4617998
--- /dev/null
+++ b/integration-tests/init.ps1
@@ -0,0 +1,136 @@
+[CmdletBinding()]
+Param (
+ [Parameter(Mandatory = $true)]
+ [string]
+ [ValidateNotNullOrEmpty()]
+ $LicenseXmlPath,
+
+ [string]
+ $HostName = "dockerexamples",
+
+ # We do not need to use [SecureString] here since the value will be stored unencrypted in .env,
+ # and used only for transient local example environment.
+ [string]
+ $SitecoreAdminPassword = "Password12345",
+
+ # We do not need to use [SecureString] here since the value will be stored unencrypted in .env,
+ # and used only for transient local example environment.
+ [string]
+ $SqlSaPassword = "Password12345"
+)
+
+$ErrorActionPreference = "Stop";
+
+if (-not (Test-Path $LicenseXmlPath)) {
+ throw "Did not find $LicenseXmlPath"
+}
+if (-not (Test-Path $LicenseXmlPath -PathType Leaf)) {
+ throw "$LicenseXmlPath is not a file"
+}
+
+# Check for Sitecore Gallery
+Import-Module PowerShellGet
+$SitecoreGallery = Get-PSRepository | Where-Object { $_.SourceLocation -eq "https://sitecore.myget.org/F/sc-powershell/api/v2" }
+if (-not $SitecoreGallery) {
+ Write-Host "Adding Sitecore PowerShell Gallery..." -ForegroundColor Green
+ Register-PSRepository -Name SitecoreGallery -SourceLocation https://sitecore.myget.org/F/sc-powershell/api/v2 -InstallationPolicy Trusted
+ $SitecoreGallery = Get-PSRepository -Name SitecoreGallery
+}
+# Install and Import SitecoreDockerTools
+$dockerToolsVersion = "10.1.4"
+Remove-Module SitecoreDockerTools -ErrorAction SilentlyContinue
+if (-not (Get-InstalledModule -Name SitecoreDockerTools -RequiredVersion $dockerToolsVersion -ErrorAction SilentlyContinue)) {
+ Write-Host "Installing SitecoreDockerTools..." -ForegroundColor Green
+ Install-Module SitecoreDockerTools -RequiredVersion $dockerToolsVersion -Scope CurrentUser -Repository $SitecoreGallery.Name
+}
+Write-Host "Importing SitecoreDockerTools..." -ForegroundColor Green
+Import-Module SitecoreDockerTools -RequiredVersion $dockerToolsVersion
+Write-SitecoreDockerWelcome
+
+###############################
+# Populate the environment file
+###############################
+
+Write-Host "Populating required .env file variables..." -ForegroundColor Green
+
+# SITECORE_ADMIN_PASSWORD
+Set-EnvFileVariable "SITECORE_ADMIN_PASSWORD" -Value $SitecoreAdminPassword
+
+# SQL_SA_PASSWORD
+Set-EnvFileVariable "SQL_SA_PASSWORD" -Value $SqlSaPassword
+
+# CD_HOST
+Set-EnvFileVariable "CD_HOST" -Value "cd.$($HostName).localhost"
+
+# CM_HOST
+Set-EnvFileVariable "CM_HOST" -Value "cm.$($HostName).localhost"
+
+# ID_HOST
+Set-EnvFileVariable "ID_HOST" -Value "id.$($HostName).localhost"
+
+# HRZ_HOST
+Set-EnvFileVariable "HRZ_HOST" -Value "hrz.$($HostName).localhost"
+
+# REPORTING_API_KEY = random 64-128 chars
+Set-EnvFileVariable "REPORTING_API_KEY" -Value (Get-SitecoreRandomString 64 -DisallowSpecial)
+
+# TELERIK_ENCRYPTION_KEY = random 64-128 chars
+Set-EnvFileVariable "TELERIK_ENCRYPTION_KEY" -Value (Get-SitecoreRandomString 128)
+
+# MEDIA_REQUEST_PROTECTION_SHARED_SECRET
+Set-EnvFileVariable "MEDIA_REQUEST_PROTECTION_SHARED_SECRET" -Value (Get-SitecoreRandomString 64)
+
+# SITECORE_IDSECRET = random 64 chars
+Set-EnvFileVariable "SITECORE_IDSECRET" -Value (Get-SitecoreRandomString 64 -DisallowSpecial)
+
+# SITECORE_ID_CERTIFICATE
+$idCertPassword = Get-SitecoreRandomString 12 -DisallowSpecial
+Set-EnvFileVariable "SITECORE_ID_CERTIFICATE" -Value (Get-SitecoreCertificateAsBase64String -DnsName "localhost" -Password (ConvertTo-SecureString -String $idCertPassword -Force -AsPlainText))
+
+# SITECORE_ID_CERTIFICATE_PASSWORD
+Set-EnvFileVariable "SITECORE_ID_CERTIFICATE_PASSWORD" -Value $idCertPassword
+
+# SITECORE_LICENSE
+Set-EnvFileVariable "SITECORE_LICENSE" -Value (ConvertTo-CompressedBase64String -Path $LicenseXmlPath)
+
+##################################
+# Configure TLS/HTTPS certificates
+##################################
+
+Push-Location docker\traefik\certs
+try {
+ $mkcert = ".\mkcert.exe"
+ if ($null -ne (Get-Command mkcert.exe -ErrorAction SilentlyContinue)) {
+ # mkcert installed in PATH
+ $mkcert = "mkcert"
+ } elseif (-not (Test-Path $mkcert)) {
+ Write-Host "Downloading and installing mkcert certificate tool..." -ForegroundColor Green
+ Invoke-WebRequest "https://github.com/FiloSottile/mkcert/releases/download/v1.4.1/mkcert-v1.4.1-windows-amd64.exe" -UseBasicParsing -OutFile mkcert.exe
+ if ((Get-FileHash mkcert.exe).Hash -ne "1BE92F598145F61CA67DD9F5C687DFEC17953548D013715FF54067B34D7C3246") {
+ Remove-Item mkcert.exe -Force
+ throw "Invalid mkcert.exe file"
+ }
+ }
+ Write-Host "Generating Traefik TLS certificate..." -ForegroundColor Green
+ & $mkcert -install
+ & $mkcert -key-file key.pem -cert-file cert.pem "*.$($HostName).localhost"
+}
+catch {
+ Write-Host "An error occurred while attempting to generate TLS certificate: $_" -ForegroundColor Red
+}
+finally {
+ Pop-Location
+}
+
+################################
+# Add Windows hosts file entries
+################################
+
+Write-Host "Adding Windows hosts file entries..." -ForegroundColor Green
+
+Add-HostsEntry "cd.$($HostName).localhost"
+Add-HostsEntry "cm.$($HostName).localhost"
+Add-HostsEntry "id.$($HostName).localhost"
+Add-HostsEntry "hrz.$($HostName).localhost"
+
+Write-Host "Done!" -ForegroundColor Green
\ No newline at end of file
diff --git a/integration-tests/nuget.config b/integration-tests/nuget.config
new file mode 100644
index 00000000..bbab12d7
--- /dev/null
+++ b/integration-tests/nuget.config
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/rebuild-images.ps1 b/integration-tests/rebuild-images.ps1
new file mode 100644
index 00000000..628b7103
--- /dev/null
+++ b/integration-tests/rebuild-images.ps1
@@ -0,0 +1,5 @@
+docker-compose build
+docker-compose -f docker-compose.yml -f docker-compose.override.sync.yml build
+docker-compose -f docker-compose.yml -f docker-compose.override.svg.yml build
+docker-compose -f docker-compose.yml -f docker-compose.override.svg.webp.yml build
+docker-compose -f docker-compose.yml -f docker-compose.override.svg.webp.avif.jxl.yml build
\ No newline at end of file
diff --git a/integration-tests/run-tests.ps1 b/integration-tests/run-tests.ps1
new file mode 100644
index 00000000..2377bf3c
--- /dev/null
+++ b/integration-tests/run-tests.ps1
@@ -0,0 +1,53 @@
+
+
+#Clean previous reports
+Get-ChildItem -Path .\docker\data\tests -Exclude ".gitkeep" -Recurse | Remove-Item -Force -Recurse -Verbose
+
+
+#Container list of tests
+$tests =@(
+ @("docker-compose up -d", "docker-compose down", "Default Dianoga async setup"),
+ @("docker-compose -f docker-compose.yml -f docker-compose.override.sync.yml up -d", "docker-compose -f docker-compose.yml -f docker-compose.override.sync.yml down","Default Dianoga sync setup"),
+ @("docker-compose -f docker-compose.yml -f docker-compose.override.svg.yml up -d", "docker-compose -f docker-compose.yml -f docker-compose.override.svg.yml down","Default Dianoga async setup with SVG enabled"),
+ @("docker-compose -f docker-compose.yml -f docker-compose.override.svg.webp.yml up -d", "docker-compose -f docker-compose.yml -f docker-compose.override.svg.webp.yml down","Default Dianoga async setup with SVG & WebP enabled"),
+ @("docker-compose -f docker-compose.yml -f docker-compose.override.svg.webp.avif.jxl.yml up -d", "docker-compose -f docker-compose.yml -f docker-compose.override.svg.webp.avif.jxl.yml down","Default Dianoga async setup with SVG & WebP & Avif & JPEG XL enabled")
+)
+
+$output = ""
+
+For($i = 0; $i -lt $tests.Length; $i++) {
+ $testName = $tests[$i][2]
+ #Clean MediaCache
+ Get-ChildItem -Path .\docker\data\mediaCache -Exclude ".gitkeep" -Recurse | Remove-Item -Force -Recurse -Verbose
+
+ $datetime = Get-Date -Format "HH:mm:ss "
+ Write-Host "$datetime Starting $testName".
+
+ Invoke-Expression $tests[$i][0]
+
+ $datetime = Get-Date -Format "HH:mm:ss "
+
+ Write-Host "$datetime $testName was started"
+ #docker container ls -f Name=dianoga_test
+ while((docker container ls -f name=dianoga_test -q ) -ne $null)
+ {
+ Start-Sleep -Seconds 30
+ $datetime = Get-Date -Format "HH:mm:ss "
+ Write-Host "$datetime Waiting for dianoga_test container to finish testing"
+ }
+
+ Invoke-Expression $tests[$i][1]
+
+ $report = Get-ChildItem .\docker\data\tests | sort creationtime -Descending | Select-Object -first 1
+ $result = Get-Content $report.FullName -Tail 1
+
+ $output += "`n======================================`n"
+ $output += "Test results for: $testName`n"
+ $output += $result
+ $output += "`n======================================`n"
+}
+
+Write-Host $output
+
+
+
diff --git a/src/Dianoga/Default Config Files/z.03.Dianoga.NextGenFormats.JpegXL.config.disabled b/src/Dianoga/Default Config Files/z.03.Dianoga.NextGenFormats.JpegXL.config.disabled
index b0c5315e..e62f6ea1 100644
--- a/src/Dianoga/Default Config Files/z.03.Dianoga.NextGenFormats.JpegXL.config.disabled
+++ b/src/Dianoga/Default Config Files/z.03.Dianoga.NextGenFormats.JpegXL.config.disabled
@@ -40,22 +40,6 @@
-q 80 --num_threads 1
-
-
-
- /App_Data/Dianoga Tools/jxl/cjxl.exe
- -q 80 --num_threads 1
-
-
-
-
-
- /App_Data/Dianoga Tools/jxl/cjxl.exe
- -q 80 --num_threads 1
-
-
\ No newline at end of file