summaryrefslogtreecommitdiffstats
path: root/client-compiler
diff options
context:
space:
mode:
authorMarc Englund <marc@vaadin.com>2012-12-14 12:08:26 +0200
committerMarc Englund <marc@vaadin.com>2012-12-14 13:50:36 +0200
commitaefc9fe8f210296e647fe12f48c5baf81229fee4 (patch)
treeacbd1e52d424f058dbe4dfe833d5c4b4e6e0bd71 /client-compiler
parent4abad6d44b062709a20406d603cdee567f67ebae (diff)
downloadvaadin-framework-aefc9fe8f210296e647fe12f48c5baf81229fee4.tar.gz
vaadin-framework-aefc9fe8f210296e647fe12f48c5baf81229fee4.zip
SassLinker for (public folder) Sass support in plain GWT, fixes #10202
Originally by Michael Vogt (+ added log message, moved) Change-Id: I565207b4fa5223f470e1e5bbdc196d4c343a8142
Diffstat (limited to 'client-compiler')
-rw-r--r--client-compiler/ivy.xml2
-rw-r--r--client-compiler/src/com/vaadin/sass/linker/SassLinker.java195
2 files changed, 197 insertions, 0 deletions
diff --git a/client-compiler/ivy.xml b/client-compiler/ivy.xml
index 1340ab2c5b..ee36e4e261 100644
--- a/client-compiler/ivy.xml
+++ b/client-compiler/ivy.xml
@@ -25,6 +25,8 @@
rev="${vaadin.version}" conf="build" />
<dependency org="com.vaadin" name="vaadin-client"
rev="${vaadin.version}" conf="build" />
+ <dependency org="com.vaadin" name="vaadin-theme-compiler"
+ rev="${vaadin.version}" conf="build" />
<dependency org="commons-collections" name="commons-collections"
rev="3.1" conf="build,ide -> default" />
diff --git a/client-compiler/src/com/vaadin/sass/linker/SassLinker.java b/client-compiler/src/com/vaadin/sass/linker/SassLinker.java
new file mode 100644
index 0000000000..82a228a166
--- /dev/null
+++ b/client-compiler/src/com/vaadin/sass/linker/SassLinker.java
@@ -0,0 +1,195 @@
+package com.vaadin.sass.linker;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.w3c.css.sac.CSSException;
+
+import com.google.gwt.core.ext.LinkerContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.AbstractLinker;
+import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.EmittedArtifact;
+import com.google.gwt.core.ext.linker.LinkerOrder;
+import com.google.gwt.core.ext.linker.LinkerOrder.Order;
+import com.google.gwt.core.ext.linker.Shardable;
+import com.vaadin.sass.internal.ScssStylesheet;
+
+/**
+ * Pre-linker that checks for the existence of SASS files in public folders,
+ * compiles them to CSS files with the SassCompiler from Vaadin and adds the CSS
+ * back into the artifact.
+ *
+ */
+@LinkerOrder(Order.PRE)
+@Shardable
+public class SassLinker extends AbstractLinker {
+
+ @Override
+ public String getDescription() {
+ return "Compiling SASS files in public folders to standard CSS";
+ }
+
+ @Override
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts, boolean onePermutation)
+ throws UnableToCompleteException {
+
+ if (!onePermutation) {
+ // The artifact to return
+ ArtifactSet toReturn = new ArtifactSet(artifacts);
+
+ // The temporary sass files provided from the artefacts
+ List<FileInfo> sassFiles = new ArrayList<FileInfo>();
+
+ // The public files are provided as inputstream, but the compiler
+ // needs real files, as they can contain references to other
+ // files. They will be stored here, with their relative paths intact
+ String tempFolderName = new Date().getTime() + File.separator;
+ File tempFolder = createTempDir(tempFolderName);
+
+ // Create the temporary files
+ for (EmittedArtifact resource : artifacts
+ .find(EmittedArtifact.class)) {
+
+ String partialPath = resource.getPartialPath();
+ if (partialPath.endsWith(".scss")) {
+
+ String fileName = partialPath;
+ File path = tempFolder;
+
+ int separatorIndex = fileName.lastIndexOf(File.separator);
+ if (-1 != separatorIndex) {
+ fileName = fileName.substring(separatorIndex + 1);
+
+ String filePath = partialPath.substring(0,
+ separatorIndex);
+ path = createTempDir(tempFolderName + filePath);
+ }
+
+ File tempfile = new File(path, fileName);
+ try {
+ boolean fileCreated = tempfile.createNewFile();
+ if (fileCreated) {
+
+ // write the received inputstream to the temp file
+ writeFromInputStream(resource.getContents(logger),
+ tempfile);
+
+ // Store the file info for the compilation
+ sassFiles.add(new FileInfo(tempfile, partialPath));
+
+ // In my oppinion, the SASS file does not need to be
+ // output to the web content, as they can't be used
+ // there
+ toReturn.remove(resource);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // Compile the files and store them in the artifact
+ logger.log(TreeLogger.INFO, "Processing " + sassFiles.size()
+ + " Sass file(s)");
+ for (FileInfo fileInfo : sassFiles) {
+ logger.log(TreeLogger.INFO, " " + fileInfo.originalScssPath
+ + " -> " + fileInfo.getOriginalCssPath());
+
+ ScssStylesheet scss;
+
+ try {
+ scss = ScssStylesheet.get(fileInfo.getAbsolutePath());
+ scss.compile();
+ InputStream is = new ByteArrayInputStream(scss.toString()
+ .getBytes());
+
+ toReturn.add(this.emitInputStream(logger, is,
+ fileInfo.getOriginalCssPath()));
+ } catch (CSSException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return toReturn;
+ }
+
+ return artifacts;
+ }
+
+ private void writeFromInputStream(InputStream contents, File tempfile)
+ throws IOException {
+ // write the inputStream to a FileOutputStream
+ OutputStream out = new FileOutputStream(tempfile);
+
+ int read = 0;
+ byte[] bytes = new byte[1024];
+
+ while ((read = contents.read(bytes)) != -1) {
+ out.write(bytes, 0, read);
+ }
+
+ contents.close();
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Create folder in temporary space on disk.
+ *
+ * @param partialPath
+ * @return
+ */
+ private File createTempDir(String partialPath) {
+ String baseTempPath = System.getProperty("java.io.tmpdir");
+
+ File tempDir = new File(baseTempPath + File.separator + partialPath);
+ if (!tempDir.exists()) {
+ tempDir.mkdir();
+ }
+
+ tempDir.deleteOnExit();
+ return tempDir;
+ }
+
+ /**
+ * Temporal storage for file info from Artifact
+ *
+ */
+ private class FileInfo {
+ private String originalScssPath;
+ private File file;
+
+ public FileInfo(File file, String originalScssPath) {
+ this.file = file;
+ this.originalScssPath = originalScssPath;
+ }
+
+ public String getAbsolutePath() {
+ return file.getAbsolutePath();
+ }
+
+ public String getOriginalCssPath() {
+ return originalScssPath.substring(0, originalScssPath.length() - 5)
+ + ".css";
+ }
+ }
+
+}
a id='n550' href='#n550'>550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
# content of service-account-credentials.json, used to access to Google Cloud Platform
gcp_credentials: ENCRYPTED[!e5f7207bd8d02d383733bef47e18296ac32e3b7d22eb480354e8dd8fdc0004be45a8a4e72c797bd66ee94eb3340fa363!]

env:
  GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-XX:+PrintFlagsFinal -XshowSettings:vm -XX:+HeapDumpOnOutOfMemoryError -XX:+UnlockExperimentalVMOptions -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -Duser.language=en -Duser.country=US"
  # to be replaced by other credentials
  ARTIFACTORY_PRIVATE_USERNAME: repox-private-reader
  ARTIFACTORY_PRIVATE_PASSWORD: ENCRYPTED[!35ca4446564213d4fd2d1a96e42a871d5de6e6aac4e1dd3e89342892a60a2badf74a966bcc8e885e9c9d09a775ffe4c0!]
  ARTIFACTORY_DEPLOY_USERNAME: repox-qa-deployer
  ARTIFACTORY_DEPLOY_PASSWORD: ENCRYPTED[!d484e19f33c9ce63b165f70e414a33b1ac6c215a126791aacbf8059626caf0fd8a78e999a20af5c1a4ba01c0b0247921!]
  ARTIFACTORY_API_KEY: ENCRYPTED[60f92cec4bf8446867dce41fe8dc77457f10065b82a24bfa3924d496aa1c14b89b531b86c3a34274abb12cf9a4cb36c4]
  # download licenses for testing commercial editions
  GITHUB_TOKEN: ENCRYPTED[!f272985ea5b49b3cf9c414b98de6a8e9096be47bfcee52f33311ba3131a2af637c1b956f49585b7757dd84b7c030233a!]
  # use a permanent GitHub access token to perform a clone (by default CirrusCI uses a temporary one)
  CIRRUS_REPO_CLONE_TOKEN: ENCRYPTED[f20fee6519296187a473964e60afb08a1bbdc889a624fad0297b41a21d8697f8d2da4d2d245194ade630dcf46b4b581e]
  # notifications to burgr
  BURGR_URL: ENCRYPTED[24fba83587c1e9ed372b6cfdf12e4739ebe3b6e5b5082f1a2a742e840dd2e4b61fd5e281bf2632b22b3ad346c650c05c]
  BURGR_USERNAME: ENCRYPTED[cf7bfb936025fb763013bbfef0ab5723c0d9b53f135d79af36f9defa933f4b5fc72842bd83a97ce9b614503c1b77e6da]
  BURGR_PASSWORD: ENCRYPTED[bc554fc6a06c9f14cc9924cefad0a69e962a905b6d1609fc9357d458b45fc52ac74c960ad9c7382a0691433fa9dcd483]
  # analysis on next.sonarqube.com
  SONARQUBE_NEXT_TOKEN: ENCRYPTED[!0d599f9fb1613db33388821ca04af23f090729902b4421ad0a53cea8393d1e9039f2e47d65a246781b0e2c3718c172a1!]
  # to trigger docs deployment
  BUDDY_WORKS_TOKEN: ENCRYPTED[9ba648f3167b6f0c0befbba2f816bfffd53260fef06fb0fe8bba0a19ae4808c8b1567c5dcee2a2ee5299a5969058f495]
  ELASTIC_PWD: ENCRYPTED[78c127034b9f06bc1b5ad7a520de2da094f3eaf1dcb35f12b0f178fa90ce2fd157bd6f9feece9bf3a54b4e3805bc39fb]
  CIRRUS_LOG_TIMESTAMP: true

auto_cancellation: $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH !=~ 'branch.*' && $CIRRUS_BRANCH != 'dogfood-on-next'

only_nightly_depending_on_build_template: &ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  depends_on: build
  # Comment the following line and commit with message "DO NOT MERGE" in order to run
  # this task on your branch
  only_if: $CIRRUS_BRANCH == "branch-nightly-build"

only_default_depending_on_build_template: &ONLY_DEFAUT_DEPENDING_ON_BUILD_TEMPLATE
  depends_on: build
  only_if: >-
           $CIRRUS_BRANCH !=~ "dogfood/.*" &&
           $CIRRUS_BRANCH != "public_master" &&
           $CIRRUS_CRON == ""

docker_build_container_template: &GKE_CONTAINER_TEMPLATE
  dockerfile: private/docker/Dockerfile-build
  builder_image_project: sonarqube-team
  builder_image_name: docker-builder-v20200915
  cluster_name: cirrus-ci-cluster
  zone: us-central1-a
  namespace: default
  cpu: 1
  memory: 1Gb

oracle_additional_container_template: &ORACLE_ADDITIONAL_CONTAINER_TEMPLATE
  name: oracle
  image: us.gcr.io/sonarqube-team/oracle12:0.0.1 # see https://github.com/SonarSource/vms/blob/master/docker/README.md#oracle-12c to build it
  port: 1521
  cpu: 2
  memory: 5Gb
  env:
    ORACLE_PWD: sonarqube

postgres_additional_container_template: &POSTGRES_ADDITIONAL_CONTAINER_TEMPLATE
  name: postgres
  image: postgres:13.2
  port: 5432
  cpu: 1
  memory: 1Gb
  env:
    POSTGRES_USER: postgres
    POSTGRES_PASSWORD: postgres

reports_junit_on_failure_template: &REPORTS_JUNIT_ON_FAILURE_TEMPLATE
  jest_junit_cleanup_script: >
    find . -type f -wholename "**/build/test-results/test-jest/junit.xml" -exec
    xmlstarlet edit --inplace --delete '//testsuite[@errors=0 and @failures=0]' {} \;
  reports_artifacts:
    path: "**/build/reports/**/*"
  junit_artifacts:
    path: "**/build/test-results/**/*.xml"
    format: junit

screenshots_on_failure_template: &REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE
  <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE
  screenshots_artifacts:
    path: "**/build/screenshots/**/*"

yarn_cache_template: &YARN_CACHE_TEMPLATE
  yarn_cache:
    folder: "~/.yarn/berry/cache"
    fingerprint_script: |
      cat \
        server/sonar-web/yarn.lock \
        server/sonar-docs/yarn.lock \
        private/core-extension-governance/yarn.lock \
        private/core-extension-license/yarn.lock \
        private/core-extension-securityreport/yarn.lock

custom_clone_script_template: &CUSTOM_CLONE_SCRIPT_TEMPLATE
  clone_script: |
    git clone --recursive --branch=$CIRRUS_BRANCH https://x-access-token:${CIRRUS_REPO_CLONE_TOKEN}@github.com/${CIRRUS_REPO_FULL_NAME}.git $CIRRUS_WORKING_DIR --depth=1
    git fetch origin $CIRRUS_CHANGE_IN_REPO --depth=1
    git reset --hard $CIRRUS_CHANGE_IN_REPO

profile_artifacts_template: &PROFILE_ARTIFACTS_TEMPLATE
  profile_artifacts:
    path: "**/build/reports/profile/**/*"

build_task:
  <<: *YARN_CACHE_TEMPLATE
  only_if: >-
           $CIRRUS_BRANCH !=~ "dogfood/.*" &&
           $CIRRUS_BRANCH != "public_master" &&
           $CIRRUS_CRON == ""
  timeout_in: 90m
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 7.5
    memory: 8Gb
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    ORG_GRADLE_PROJECT_signingKey: ENCRYPTED[!cc216dfe592f79db8006f2a591f8f98b40aa2b078e92025623594976fd32f6864c1e6b6ba74b50647f608e2418e6c336!]
    ORG_GRADLE_PROJECT_signingPassword: ENCRYPTED[!314a8fc344f45e462dd5e8dccd741d7562283a825e78ebca27d4ae9db8e65ce618e7f6aece386b2782a5abe5171467bd!]
    ORG_GRADLE_PROJECT_signingKeyId: 0x7DCD4258
  elasticsearch_distribution_cache:
    folder: sonar-application/build/elasticsearch-**.tar.gz
  script:
    - ./private/cirrus/cirrus-build.sh
  on_failure:
    reports_artifacts:
      path: "**/build/reports/**/*"
  always:
    <<: *PROFILE_ARTIFACTS_TEMPLATE

validate_task:
  <<: *ONLY_DEFAUT_DEPENDING_ON_BUILD_TEMPLATE
  <<: *YARN_CACHE_TEMPLATE
  timeout_in: 90m
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 6.5
    memory: 24Gb
    additional_containers:
      - <<: *POSTGRES_ADDITIONAL_CONTAINER_TEMPLATE
  script:
    - ./private/cirrus/cirrus-validate.sh postgres106
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE
  always:
    <<: *PROFILE_ARTIFACTS_TEMPLATE

yarn_check-ci_task:
  <<: *ONLY_DEFAUT_DEPENDING_ON_BUILD_TEMPLATE
  <<: *YARN_CACHE_TEMPLATE
  timeout_in: 90m
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 4
    memory: 8Gb
  script: |
    ./private/cirrus/cirrus-env.sh YARN
    gradle yarn_check-ci --profile
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE
  always:
    <<: *PROFILE_ARTIFACTS_TEMPLATE

qa_task:
  <<: *ONLY_DEFAUT_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 3
    memory: 7Gb
    additional_containers:
      - <<: *POSTGRES_ADDITIONAL_CONTAINER_TEMPLATE
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    matrix:
      - QA_CATEGORY: Cat1
      - QA_CATEGORY: Cat2
      - QA_CATEGORY: Cat3
      - QA_CATEGORY: Cat4
      - QA_CATEGORY: Cat5
      - QA_CATEGORY: Cat6
      - QA_CATEGORY: Cat7
      - QA_CATEGORY: Authentication
      - QA_CATEGORY: Gov
      - QA_CATEGORY: Dev
      - QA_CATEGORY: License
      - QA_CATEGORY: Branch
      - QA_CATEGORY: Upgrade
  script:
    - ./private/cirrus/cirrus-qa.sh postgres106
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

task: #bitbucket
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 3
    memory: 7Gb
    additional_containers:
      - <<: *POSTGRES_ADDITIONAL_CONTAINER_TEMPLATE
  maven_cache:
    folder: ~/.m2
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: BITBUCKET
  matrix:
    - name: qa_bitbucket_5.15.0
      bitbucket_background_script: ./private/cirrus/cirrus-start-bitbucket.sh 5.15.0
    - name: qa_bitbucket_latest
      bitbucket_background_script: ./private/cirrus/cirrus-start-bitbucket.sh LATEST
  wait_for_bitbucket_to_boot_script: secs=3600; endTime=$(( $(date +%s) + secs )); while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:7990/bitbucket/status)" != "200" ]] || [ $(date +%s) -gt $endTime ]; do sleep 5; done
  script:
    - ./private/cirrus/cirrus-qa.sh postgres106
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

qa_bb_cloud_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 2.4
    memory: 5Gb
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: BITBUCKET_CLOUD
    BBC_CLIENT_ID: ENCRYPTED[f1c2c57d5f02885345b3db5776a3b28f5dbcc89723809f73ad05ada903ece9584f1dfe61b026c10eabd72c75d1258bac]
    BBC_CLIENT_SECRET: ENCRYPTED[39cc89ce4695c243fd688e687879bd473a60882fd30ba8613d6697e5d2b04e2017c68cae3a9a7ed9704f69c52bf229ee]
    BBC_READ_REPOS_APP_PASSWORD: ENCRYPTED[d33b02d02987e188b5cec2a14f6ddd04d1fcac39ed5d6ced08891fc562ebb6721c9fbf307c0eba81df78c83f75b3c27c]
    BBC_USERNAME: ENCRYPTED[f0af9be9d2fbaa55fbf69e4fce706ebc9131e0dc22cf8bce5d7ab2e0c2b57aff3ddbf6b3b77166e803a6000276256cea]
  gradle_cache:
    folder: ~/.gradle/caches
  script:
    - ./private/cirrus/cirrus-qa.sh h2
  cleanup_before_cache_script:
    - ./private/cirrus/cleanup-gradle-cache.sh
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

qa_ha_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 2.4
    memory: 10Gb
    additional_containers:
      - <<: *POSTGRES_ADDITIONAL_CONTAINER_TEMPLATE
  env:
      # No need to clone the full history.
      # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
      # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: HA
  gradle_cache:
    folder: ~/.gradle/caches
  script:
    - ./private/cirrus/cirrus-qa.sh postgres106
  cleanup_before_cache_script:
    - ./private/cirrus/cleanup-gradle-cache.sh
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

docker_gitlab_container_build_task:
  only_if: $CIRRUS_BRANCH == "branch-nightly-build"
  gce_instance:
    image_project: sonarqube-team
    image_family: docker-builder
    zone: us-central1-a
    preemptible: true
    disk: 10
    cpu: 4
    memory: 8G
  env:
    CIRRUS_CLONE_DEPTH: 3
    matrix:
      - GITLAB_TAG: latest
      - GITLAB_TAG: 11.7.0-ce.0
  build_script:
    - docker pull "us.gcr.io/sonarqube-team/sq-gitlab:${GITLAB_TAG}" || true
    - docker build --build-arg "GITLAB_TAG=${GITLAB_TAG}" --cache-from "us.gcr.io/sonarqube-team/sq-gitlab:${GITLAB_TAG}" -t "us.gcr.io/sonarqube-team/sq-gitlab:${GITLAB_TAG}" private/docker/gitlab/
    - docker push "us.gcr.io/sonarqube-team/sq-gitlab:${GITLAB_TAG}"

# GitLab QA is executed in a dedicated task in order to not slow down the pipeline, as a GitLab on-prem server docker image is required.
qa_gitlab_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  depends_on:
    - build
    - docker_gitlab_container_build
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 2.4
    memory: 5Gb
    use_in_memory_disk: true
    additional_containers:
      - name: gitlab
        ports:
          - 80
          - 443
        cpu: 2
        memory: 5Gb
        matrix:
          - image: us.gcr.io/sonarqube-team/sq-gitlab:latest
          - image: us.gcr.io/sonarqube-team/sq-gitlab:11.7.0-ce.0
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: GITLAB
  gradle_cache:
    folder: ~/.gradle/caches
  script:
    - ./private/cirrus/cirrus-qa.sh h2
  cleanup_before_cache_script:
    - ./private/cirrus/cleanup-gradle-cache.sh
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

# Azure QA is executed in a dedicated task in order to not slow down the pipeline.
qa_azure_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 2.4
    memory: 5Gb
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: AZURE
    AZURE_USERNAME_LOGIN: ENCRYPTED[dcdf19769c1501408ebc22670c76d5e375cd739de2df5dfa3f215aa795296dfb257dbbcbe9bdfd33135feb04421fea1f]
    AZURE_CODE_READ_AND_WRITE_TOKEN: ENCRYPTED[eddc3448b40e72310f24f21241bdc1243860139d1a5aad593b016baedf03e4bba3f9e3d8d9f6329fe3b587966a8112d2]
    AZURE_FULL_ACCESS_TOKEN: ENCRYPTED[58779d6588e2e10d1b6f98fcc58a46957f8ef3a18e29d79abc6aa8d69ea55c23d8708e1f1af626464d309b1c7c087985]
  gradle_cache:
    folder: ~/.gradle/caches
  script:
    - ./private/cirrus/cirrus-qa.sh h2
  cleanup_before_cache_script:
    - ./private/cirrus/cleanup-gradle-cache.sh
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

# SAML QA is executed in a dedicated task in order to not slow down the pipeline, as a Keycloak server docker image is required.
qa_saml_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 2.4
    memory: 10Gb
    additional_containers:
      - name: keycloak
        image: jboss/keycloak:7.0.0
        port: 8080
        cpu: 1
        memory: 1Gb
        env:
          KEYCLOAK_USER: admin
          KEYCLOAK_PASSWORD: admin
  env:
      # No need to clone the full history.
      # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
      # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: SAML
  gradle_cache:
    folder: ~/.gradle/caches
  script:
    - ./private/cirrus/cirrus-qa.sh h2
  cleanup_before_cache_script:
    - ./private/cirrus/cleanup-gradle-cache.sh
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

# LDAP QA is executed in a dedicated task in order to not slow down the pipeline, as a LDAP server and SonarQube server are re-started on each test.
qa_ldap_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 2.4
    memory: 10Gb
  env:
      # No need to clone the full history.
      # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
      # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    QA_CATEGORY: LDAP
  gradle_cache:
    folder: ~/.gradle/caches
  script:
    - ./private/cirrus/cirrus-qa.sh h2
  cleanup_before_cache_script:
    - ./private/cirrus/cleanup-gradle-cache.sh
  on_failure:
    <<: *REPORTS_JUNIT_SCREENSHOTS_ON_FAILURE_TEMPLATE

promote_task:
  <<: *ONLY_DEFAUT_DEPENDING_ON_BUILD_TEMPLATE
  depends_on:
    - build
    - validate
    - qa
    - qa_saml
    - qa_ldap
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
  stateful: true
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
  script:
    - ./private/cirrus/cirrus-promote.sh

deploy_docs_task:
  depends_on: promote
  skip: true
  only_if: $CIRRUS_BRANCH == 'dogfood-on-next'
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
  script:
    - ./private/cirrus/cirrus-trigger-deploy-docs.sh

package_docker_task:
  depends_on: promote
  only_if: $CIRRUS_BRANCH == 'dogfood-on-next'
  gce_instance:
    image_project: sonarqube-team
    image_family: docker-builder
    zone: us-central1-a
    disk: 10
    cpu: 4
    memory: 8G
  <<: *CUSTOM_CLONE_SCRIPT_TEMPLATE
  install_tooling_script:
    - ./private/cirrus/cirrus-tooling-for-package-docker.sh
  package_script:
    - ./private/cirrus/cirrus-package-docker.sh

sql_mssql2017_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    memory: 5Gb
    additional_containers:
      - name: mssql
        image: mcr.microsoft.com/mssql/server:2019-GA-ubuntu-16.04
        port: 1433
        cpu: 2
        memory: 5Gb
        env:
          MSSQL_PID: Developer # this is the default edition
          ACCEPT_EULA: Y
          SA_PASSWORD: sonarqube!1
  script:
    - ./private/cirrus/cirrus-db-unit-test.sh mssql2017
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE

# this is the oldest compatible version of PostgreSQL
sql_postgres96_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    memory: 5Gb
    additional_containers:
      - <<: *POSTGRES_ADDITIONAL_CONTAINER_TEMPLATE
        image: postgres:9.6
  script:
    - ./private/cirrus/cirrus-db-unit-test.sh postgres96
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE

sql_oracle12_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    memory: 5Gb
    additional_containers:
      - <<: *ORACLE_ADDITIONAL_CONTAINER_TEMPLATE
  script:
    - ./private/cirrus/cirrus-db-unit-test.sh oracle12
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE

upgd_mssql2019_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 1.5
    memory: 6Gb
    additional_containers:
      - name: mssql
        image: mcr.microsoft.com/mssql/server:2019-GA-ubuntu-16.04
        port: 1433
        cpu: 2
        memory: 5Gb
        env:
          MSSQL_PID: Developer # this is the default edition
          ACCEPT_EULA: Y
          SA_PASSWORD: sonarqube!1
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    matrix:
      QA_CATEGORY: Upgrade
  script:
    - ./private/cirrus/cirrus-qa.sh mssql2017
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE

upgd_oracle12_task:
  <<: *ONLY_NIGHTLY_DEPENDING_ON_BUILD_TEMPLATE
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 1.5
    memory: 6Gb
    additional_containers:
      - <<: *ORACLE_ADDITIONAL_CONTAINER_TEMPLATE
  env:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    matrix:
      QA_CATEGORY: Upgrade
  script:
    - ./private/cirrus/cirrus-qa.sh oracle12
  on_failure:
    <<: *REPORTS_JUNIT_ON_FAILURE_TEMPLATE

# Software Composition Analysis (SCA): check potential vulnerabilities in dependencies.
# Note that license compliance of dependencies is not checked for now.
owasp_check_task:
  only_if: >-
           $CIRRUS_CRON == "nightly" ||
           $CIRRUS_CRON == "weekly-latest" ||
           $CIRRUS_CRON == "weekly-lts" ||
           changesInclude('private/owasp/*.xml')
  <<: *YARN_CACHE_TEMPLATE
  timeout_in: 30m
  gke_container:
    <<: *GKE_CONTAINER_TEMPLATE
    cpu: 1.7
    memory: 4Gb
  environment:
    # No need to clone the full history.
    # Depth of 1 is not enough because it would fail the build in case of consecutive pushes
    # (example of error: "Hard resetting to c968ecaf7a1942dacecd78480b3751ac74d53c33...Failed to force reset to c968ecaf7a1942dacecd78480b3751ac74d53c33: object not found!")
    CIRRUS_CLONE_DEPTH: 50
    SLACK_WEBHOOK_SQ: ENCRYPTED[dec8e4350cbea3b94d63098558bcb3ae9e79b71c2b6286fcfb9eb80c0953b6448b10f7271b07b5e75e52f362c25d7a8f]
  script:
    - gradle dependencyCheckAggregate
  on_failure:
    slack_notification_script:
      - ./private/cirrus/cirrus-owasp-notification.sh
  always:
    reports_artifacts:
      path: "build/reports/*"