diff --git a/CC.md b/CC.md new file mode 100644 index 0000000..2c41393 --- /dev/null +++ b/CC.md @@ -0,0 +1,69 @@ + +## Usage examples for PiT tests in control-center + +##### Run proxy +./scripts/pit/run.sh --proxy + +##### Delete cluster in DO +./scripts/pit/run.sh --proxy --delete --vendor=do + +##### Install cluster and helm chart for a specific CC version +./scripts/pit/run.sh --starters=control-center --keep-cc \ + --cc-version=1.3.0-beta2 \ + --skip-pw + +##### Compile apps and CC for a specific platform version, and load local images in cluster +./scripts/pit/run.sh --starters=control-center --keep-cc \ + --version=24.8.0.beta2 \ + --skip-current \ + --skip-helm \ + --skip-pw + +##### Push local images to docker central (need to be build as above) +CCPUSH=true \ +./scripts/pit/run.sh --starters=control-center --keep-cc \ + --version=24.8.0.beta2 \ + --skip-current \ + --skip-build \ + --skip-helm \ + --skip-pw + +./scripts/pit/run.sh --function pushLocalToDockerhub next + +##### Install test apps and run tests for new version (needs to have everything set as above) +./scripts/pit/run.sh --starters=control-center --keep-cc \ + --version=24.8.0.beta2 \ + --skip-current \ + --skip-build \ + --skip-helm \ + --keep-apps \ + --headed + +##### Run browser tests without headed slow-motion +FAST=true \ +./scripts/pit/run.sh --starters=control-center --keep-cc \ + --version=24.8.0.beta2 \ + --skip-current \ + --skip-build \ + --skip-helm \ + --keep-apps \ + --headed + +##### Remove tests apps from CC +CC_TESTS=cc-remove-apps.js \ +./scripts/pit/run.sh --starters=control-center --keep-cc \ + --offline \ + --skip-setup \ + --headed + +##### Create a cluster in DO with latest version of CC, compile apps and deploy then +FAST=true ./scripts/pit/run.sh \ + --starters=control-center --keep-cc --version=24.8.0.beta2 --headed --skip-current --vendor=do + + + + + + + + diff --git a/README.md b/README.md index 78f9c5d..4b80f36 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,3 @@ -# [Platform-In-Test Script] - -# How To Use - -``` -./scripts/pit/run.sh --help -``` - -``` Use: ./scripts/pit/run.sh with the next options: --version=string Vaadin version to test, if not given it only tests current stable, otherwise it runs tests against current stable and then against given version. @@ -23,13 +14,15 @@ Use: ./scripts/pit/run.sh with the next options: --skip-prod Skip production validations --skip-dev Skip dev-mode validations --skip-clean Do not clean maven cache - --skip-helm Do not re-install control-center with helm and continue running tests, implies (--offline, --skip-build, --keep-cc) + --skip-helm Do not re-install control-center with helm and continue running tests, implies (--offline, --keep-cc) --skip-pw Do not run playwright tests --cluster=name Run tests in an existing k8s cluster --vendor=name Use a specific cluster vendor to run control-center tests options: [dd, kind, do] (default: kind) --keep-cc Keep control-center running after tests + --keep-apps Keep installed apps in control-center, implies --keep-cc --proxy-cc Forward port 443 from k8s cluster to localhost --events-cc Display events from control-center + --cc-version Install this version for current --skip-build Skip building the docker images for control-center --delete-cluster Delete the cluster/s --dashboard=* Install kubernetes dashboard, options [install, uninstall] (default: install) @@ -113,7 +106,4 @@ Use: ./scripts/pit/run.sh with the next options: · designer-tutorial · walking-skeleton:v24.7-hybrid · releases-graph -``` - - - + · expo-flow \ No newline at end of file diff --git a/scripts/pit/its/cc-identity-management.js b/scripts/pit/its/cc-identity-management.js index 3b12a86..eea0898 100644 --- a/scripts/pit/its/cc-identity-management.js +++ b/scripts/pit/its/cc-identity-management.js @@ -112,6 +112,7 @@ const {log, err, args, createPage, closePage, takeScreenshot, waitForServerReady await pageApp.getByRole('button', {name: 'Sign In'}).click() await takeScreenshot(pageApp, __filename, `logged-in-${app}`); await expect(pageApp.getByRole('button', { name: 'New order' })).toBeVisible(); + await closePage(pageApp); log('Cleaning up...\n'); try { @@ -142,13 +143,13 @@ const {log, err, args, createPage, closePage, takeScreenshot, waitForServerReady await page.getByLabel('Replicas').fill('1'); await page.getByRole('button', { name: 'Update' }).click(); - await pageApp.waitForTimeout(30000); + pageApp = await createPage(arg.headless, arg.ignoreHTTPSErrors); await waitForServerReady(pageApp, appUrl); await takeScreenshot(pageApp, __filename, 'app-after-cleanup'); } catch (error) { err(`Error cleaning up: ${error}\n`); await takeScreenshot(page, __filename, 'error-cleaning'); } - await closePage(pageApp); await closePage(page); + await closePage(pageApp); })(); diff --git a/scripts/pit/its/cc-install-apps.js b/scripts/pit/its/cc-install-apps.js index 898613d..8f0355e 100644 --- a/scripts/pit/its/cc-install-apps.js +++ b/scripts/pit/its/cc-install-apps.js @@ -1,9 +1,11 @@ const { expect} = require('@playwright/test'); const fs = require('fs'); -const {log, err, args, run, createPage, closePage, takeScreenshot, waitForServerReady} = require('./test-utils'); +const {log, args, run, createPage, closePage, takeScreenshot, waitForServerReady} = require('./test-utils'); const arg = args(); let count = 0; +const gracePeriodSecs = 90; +const waitForReadyMsecs = 185000; async function installApp(app, page) { const host = arg.url.replace(/^.*:\/\//, '').replace(/\/.*$/, ''); @@ -12,7 +14,7 @@ async function installApp(app, page) { const cert = [ domain, uri ].map(a => `${a}.pem`).filter( a => fs.existsSync(a))[0] const tag = arg.tag || 'latest'; const registry = arg.registry || 'k8sdemos'; - console.log(`Installing App: ${app} URI: ${uri} Cert: ${cert}`); + log(`Installing App: ${app} URI: ${uri} Cert: ${cert} Img: ${registry}/${app}:${tag}`); await page.getByRole('listitem').filter({ hasText: 'Settings'}).click() await page.getByRole('button', {name: /Create|New/}).click() @@ -25,8 +27,20 @@ async function installApp(app, page) { await page.getByPlaceholder('Image Pull Secret').locator('input').fill(arg.secret); await takeScreenshot(page, __filename, `form-with-secret-${app}`); } - await page.getByLabel('Startup Delay (secs)').fill(process.env.GITHUB_ACTIONS ? '90' : '90'); + await page.getByLabel('Startup Delay (secs)').fill(`${gracePeriodSecs}`); + + await page.getByRole('button', {name: 'Environment Variable'}).click(); + await takeScreenshot(page, __filename, `env-dialog-opened-${app}`); + + const envDialog = page.getByRole('dialog', { name: 'Environment Variables' }); + await envDialog.getByPlaceholder('Name').locator('input').fill('SPRING_FLYWAY_ENABLED'); + await envDialog.getByPlaceholder('Value').locator('input').fill('false'); + await envDialog.getByLabel("Add").click(); + await takeScreenshot(page, __filename, `env-dialog-filled-${app}`); + await envDialog.getByLabel("Close").click(); + await page.getByLabel('Application URI', {exact: true}).locator('input[type="text"]').fill(uri) + if (cert) { log(`Uploading certificate ${cert} for ${app}...\n`); await page.getByLabel('Upload').click(); @@ -37,7 +51,6 @@ async function installApp(app, page) { await takeScreenshot(page, __filename, `form-filled-${app}`); await page.locator('.detail-layout').getByRole('button', {name: 'Deploy'}).click(); } else { - log(`No certificate found for ${app}...\n`); log(`No certificate found for ${app}\n`); run(`pwd`); run(`ls -l`); @@ -70,27 +83,27 @@ async function installApp(app, page) { await page.getByRole('button', {name: 'Sign In'}).click() await takeScreenshot(page, __filename, 'logged-in'); - for (const app of ['bakery-cc', 'bakery']) { + const apps = ['cc-starter', 'bakery-cc', 'bakery']; + for (const app of apps) { await installApp(app, page); } await takeScreenshot(page, __filename, 'installed-apps'); const startTime = Date.now(); - log(`Giving a grace period of 40 secs to wait for 2 apps to be avalable ...\n`); - await page.waitForTimeout(40000); + log(`Giving a grace period of ${gracePeriodSecs} secs to wait for ${apps.length} apps to be avalable ...\n`); + await page.waitForTimeout(gracePeriodSecs); await page.reload(); - log(`Waiting for 2 applications to be available in dashboard ...\n`); + log(`Waiting for ${apps.length} applications to be available in dashboard ...\n`); await takeScreenshot(page, __filename, 'waiting for apps'); const selector = 'vaadin-grid-cell-content span[theme="badge success"]'; - await expect(page.locator(selector).nth(0)).toBeVisible({ timeout: 280000 }); - const firstAppTime = (Date.now() - startTime) / 1000; - await takeScreenshot(page, __filename, 'app-1-available'); - log(`First application is available after ${firstAppTime.toFixed(2)} seconds\n`); - - await expect(page.locator(selector).nth(1)).toBeVisible({ timeout: 280000 }); - const secondAppTime = (Date.now() - startTime) / 1000; - await takeScreenshot(page, __filename, 'app-2-available'); - log(`Second application is available after ${secondAppTime.toFixed(2)} seconds\n`); + + for (let i = 0; i < apps.length; i++) { + await expect(page.locator(selector).nth(i)).toBeVisible({ timeout: waitForReadyMsecs }); + const firstAppTime = (Date.now() - startTime) / 1000; + await takeScreenshot(page, __filename, 'app-1-available'); + log(`application ${i + 1} is available after ${firstAppTime.toFixed(2)} seconds\n`); + } + await closePage(page); })(); diff --git a/scripts/pit/its/cc-remove-apps.js b/scripts/pit/its/cc-remove-apps.js new file mode 100644 index 0000000..f9430bf --- /dev/null +++ b/scripts/pit/its/cc-remove-apps.js @@ -0,0 +1,55 @@ +const {log, args, createPage, closePage, takeScreenshot, waitForServerReady} = require('./test-utils'); + +const arg = args(); + +async function remove(app, page) { + log(`Removing ${app}...\n`); + await page.getByRole('link', { name: 'Settings', }).click(); + await takeScreenshot(page, __filename, 'settings'); + + const anchorSelector = `//vaadin-grid-cell-content[.//span[normalize-space(text())="${app}"]]`; + const anchors = page.locator(anchorSelector); + const c = await anchors.count(); + if (c <= 0) { + log(`App ${app} not found`); + return; + } + if (c == 1) { + const text = await anchors.nth(0).textContent(); + log(`Found one element ${text}`); + } + if (c > 1) { + log(`App ${app} link found multiple times`); + for (let i = 0; i < c; i++) { + const text = await anchors.nth(i).textContent(); + log(`Element ${i}: ${text}`); + } + } + await anchors.nth(0).click(); + + await page.getByRole('button', { name: 'Delete' }).click(); + await page.getByLabel('I understand that this will').check(); + await page.getByRole('button', { name: 'Delete' }).click(); +} + +(async () => { + if (!arg.login) { + log(`Skipping the setup of Control center because of missing --email= parameter\n`) + process.exit(1); + } + const page = await createPage(arg.headless, arg.ignoreHTTPSErrors); + await waitForServerReady(page, arg.url); + await takeScreenshot(page, __filename, 'view-loaded'); + + log(`Logging in as ${arg.login} ${arg.pass}...\n`); + await page.getByLabel('Email').fill(arg.login); + await page.getByLabel('Password').fill(arg.pass); + await page.getByRole('button', {name: 'Sign In'}).click() + await takeScreenshot(page, __filename, 'logged-in'); + + for (const app of ['bakery-cc', 'bakery', 'cc-starter']) { + await remove(app, page); + } + + await closePage(page); +})(); diff --git a/scripts/pit/its/cc-setup.js b/scripts/pit/its/cc-setup.js index b307c4b..da3f493 100644 --- a/scripts/pit/its/cc-setup.js +++ b/scripts/pit/its/cc-setup.js @@ -27,22 +27,29 @@ const {log, run, args, createPage, closePage, takeScreenshot, waitForServerReady await takeScreenshot(page, __filename, 'logged-in'); - await page.getByLabel('New Password').fill(arg.pass); - await page.getByLabel('Confirm Password').fill(arg.pass); - await page.getByRole('button', { name: 'Submit' }).click(); - - await takeScreenshot(page, __filename, 'password-changed'); - - await page.getByLabel('First Name').fill(arg.login.split('@')[0]); - await page.getByLabel('Last Name').fill(arg.login.split('@')[1]); - await page.getByRole('button', { name: 'Submit' }).click(); - await takeScreenshot(page, __filename, 'user-configured'); - - await waitForServerReady(page, arg.url); + const newsPass = page.getByLabel('New Password'); + if (await newsPass.count() == 0) { + log("Seems that CC was already setup trying to login") + await page.getByLabel('Email').fill(arg.login); + await page.getByLabel('Password').fill(arg.pass); + await page.getByRole('button', {name: 'Sign In'}).click() + await takeScreenshot(page, __filename, 'logged-in'); + } else { + await newsPass.fill(arg.pass); + await page.getByLabel('Confirm Password').fill(arg.pass); + await page.getByRole('button', { name: 'Submit' }).click(); + + await takeScreenshot(page, __filename, 'password-changed'); + + await page.getByLabel('First Name').fill(arg.login.split('@')[0]); + await page.getByLabel('Last Name').fill(arg.login.split('@')[1]); + await page.getByRole('button', { name: 'Submit' }).click(); + await takeScreenshot(page, __filename, 'user-configured'); + await waitForServerReady(page, arg.url); + await page.getByRole('button', { name: 'Manage applications' }).click(); + } - await page.getByRole('button', { name: 'Manage applications' }).click(); + await page.getByRole('listitem').filter({ hasText: 'Settings'}).click() await expect(page.getByRole('heading', { name: 'Applications' })).toBeVisible(); - await page.waitForTimeout(5000); - await closePage(page); })(); \ No newline at end of file diff --git a/scripts/pit/its/test-utils.js b/scripts/pit/its/test-utils.js index 5d71d16..304edba 100644 --- a/scripts/pit/its/test-utils.js +++ b/scripts/pit/its/test-utils.js @@ -90,7 +90,7 @@ async function createPage(headless, ignoreHTTPSErrors) { const browser = await chromium.launch({ headless: headless, chromiumSandbox: false, - slowMo: headless ? 400: 1000, + slowMo: process.env.FAST ? 0 : headless ? 400: 1000, args: ['--window-position=0,0'] }); const context = await browser.newContext({ignoreHTTPSErrors: ignoreHTTPSErrors, viewport: { width: 1792, height: 970 } }); diff --git a/scripts/pit/lib/lib-args.sh b/scripts/pit/lib/lib-args.sh index 603d4e2..28393a0 100644 --- a/scripts/pit/lib/lib-args.sh +++ b/scripts/pit/lib/lib-args.sh @@ -21,13 +21,15 @@ Use: $0 with the next options: --skip-prod Skip production validations --skip-dev Skip dev-mode validations --skip-clean Do not clean maven cache - --skip-helm Do not re-install control-center with helm and continue running tests, implies (--offline, --skip-build, --keep-cc) + --skip-helm Do not re-install control-center with helm and continue running tests, implies (--offline, --keep-cc) --skip-pw Do not run playwright tests --cluster=name Run tests in an existing k8s cluster --vendor=name Use a specific cluster vendor to run control-center tests options: [dd, kind, do] (default: kind) --keep-cc Keep control-center running after tests + --keep-apps Keep installed apps in control-center, implies --keep-cc --proxy-cc Forward port 443 from k8s cluster to localhost --events-cc Display events from control-center + --cc-version Install this version for current --skip-build Skip building the docker images for control-center --delete-cluster Delete the cluster/s --dashboard=* Install kubernetes dashboard, options [install, uninstall] (default: install) @@ -51,7 +53,7 @@ EOF ## check arguments passed to `run.sh` script and set global variables checkArgs() { - VERSION=current; GITBASE="https://github.com/"; export PORT=$DEFAULT_PORT; TIMEOUT=$DEFAULT_TIMEOUT; VENDOR=kind + VERSION=current; GITBASE="https://github.com/"; export PORT=$DEFAULT_PORT; TIMEOUT=$DEFAULT_TIMEOUT; CLUSTER=pit; VENDOR=kind; CCVERSION=current while [ -n "$1" ] do arg=`echo "$1" | grep = | cut -d= -f2` @@ -82,10 +84,15 @@ checkArgs() { --skip-prod) NOPROD=true;; --skip-pw) SKIPPW=true;; --cluster=*) CLUSTER="$arg";; - --vendor=*) VENDOR="$arg";; - --skip-helm) SKIPHELM=true; SKIPBUILD=true; OFFLINE=true; KEEPCC=true ;; - --skip-build) SKIPBUILD=true;; + --vendor=*) + VENDOR="$arg" + [ "$VENDOR" = dd ] && CLUSTER="docker-desktop" + ;; + --cc-version*) CCVERSION="$arg";; --keep-cc) KEEPCC=true;; + --keep-apps) KEEPAPPS=true;; + --skip-build) SKIPBUILD=true;; + --skip-helm) OFFLINE=true; KEEPCC=true; SKIPHELM=true ;; --pnpm) PNPM="-Dpnpm.enable=true";; --vite) VITE=true;; --list*) @@ -134,9 +141,7 @@ checkArgs() { VERBOSE=true runCmd "Running CC proxy" kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443 fi exit ;; - --delete*) - deleteCluster - exit ;; + --delete-cluster) deleteCluster; exit ;; --git-ssh) GITBASE="git@github.com:" ;; --headless) HEADLESS=true ;; --headed) HEADLESS=false ;; @@ -145,7 +150,6 @@ checkArgs() { shift done - [ -z "$VENDOR" ] && VENDOR=kind - [ -z "$CLUSTER" -a "$VENDOR" = dd ] && CLUSTER="docker-desktop" - [ -z "$CLUSTER" ] && CLUSTER="pit" + + } diff --git a/scripts/pit/lib/lib-demos.sh b/scripts/pit/lib/lib-demos.sh index d94902f..b3bd71e 100755 --- a/scripts/pit/lib/lib-demos.sh +++ b/scripts/pit/lib/lib-demos.sh @@ -27,6 +27,8 @@ checkoutDemo() { cmd "cd $_workdir" cd "$_workdir" runCmd -f "Reseting local changes in $_repo" "git reset --hard HEAD" || return 1 + runCmd -f "Deleting preexisting .out files" "rm -rf *.out" + fi [ -z "$_branch" ] || (cmd "git checkout $_branch" && git checkout $_quiet "$_branch") } diff --git a/scripts/pit/lib/lib-k8s-apps.sh b/scripts/pit/lib/lib-k8s-apps.sh new file mode 100644 index 0000000..fcd3990 --- /dev/null +++ b/scripts/pit/lib/lib-k8s-apps.sh @@ -0,0 +1,90 @@ +. `dirname $0`/lib/lib-utils.sh +. `dirname $0`/lib/lib-demos.sh + +CC_APP_REPO=bakery-app-starter-flow-spring:cc-24.7 +CC_BAKERY_APP=bakery +CC_STARTER_APP=cc-starter + +## Compile bakery application, with and without CC support +compileBakery() { + APP=$CC_BAKERY_APP + log -n "* Building $APP & $APP-cc apps *" + computeMvn + checkoutDemo $CC_APP_REPO || return 1 + setDemoVersion $CC_APP_REPO $VERSION >/dev/null || return 1 + applyPatches $APP "" $APP "" || return 1 + setMvnDependencyVersion com.vaadin control-center-starter "$CCVERSION" "-Pcontrol-center" || return 1 + runToFile "'$MVN' -ntp -B clean install -Pproduction -DskipTests" "compile-$APP.out" "$VERBOSE" || return 1 + runCmd "Building Docker image for $APP" docker build -t $REGISTRY/$APP:local . || return 1 + runToFile "'$MVN' -ntp -B clean install -Pproduction,control-center -DskipTests" "compile-$APP-cc.out" "$VERBOSE" || return 1 + runCmd "Building Docker image for $APP-CC" docker build -t $REGISTRY/$APP-cc:local . || return 1 +} + +## Compile a starter downloaded from start wizard with most interesting presets selected +compileCCStarter() { + APP=$CC_STARTER_APP + log -n "* Building $APP app *" + computeMvn + PRESETS="" + APPS="latest-java partial-auth partial-controlcenter partial-kubernetes partial-prerelease partial-hilla-example-views partial-flow-example-auth-views partial-hilla-example-auth-views" + APPS="latest-java partial-auth partial-controlcenter partial-kubernetes partial-prerelease partial-hilla-example-views" + for i in $APPS + do + PRESETS="$PRESETS&preset=$i" + done + _url="https://start.vaadin.com/dl?$PRESETS&projectName=$APP" + _zip="$APP.zip" + _dir="$APP" + [ -z "$VERBOSE" ] && _silent="-s" + if [ -n "$OFFLINE" -a -d "$APP" ]; then + runCmd -f "Reseting local changes in $APP" "git --git-dir=$APP/.git --work-tree=$APP reset --hard HEAD" || return 1 + else + [ -d "$APP" ] && runCmd -f "Removing folder $APP" rm -rf $APP + runCmd -f "Downloading $1" "curl $_silent -f '$_url' -o '$_zip'" || return 1 + runCmd -f "Unzipping $_name" "unzip -q '$_zip'" && rm -f "$_zip" || return 1 + fi + + cmd "cd '$_dir'" && cd "$_dir" || return 1 + setVersion vaadin.version "$VERSION" >/dev/null || return 1 + applyPatches $APP "" $VERSION "" || return 1 + setMvnDependencyVersion com.vaadin control-center-starter "$CCVERSION" || return 1 + runToFile "'$MVN' -ntp clean package -Pproduction" "compile_$APP.out" "$VERBOSE" || return 1 + runCmd "Building Docker image for $APP" docker build -t $REGISTRY/$APP:local . || return 1 +} + +## compile and install in local maven repo control center +compileCC() { + V=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout` + [ "$CCVERSION" != "$V" ] && err "Version does not match pomVersion: $V ccVersion: $CCVERSION" && return 1 + log -n "* Building Control Center version ${V} *" + computeMvn + local D="-q -ntp" + [ -z "$VERBOSE" ] && D="-Dorg.slf4j.simpleLogger.showDateTime -Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss.SSS" + runToFile "'$MVN' $D -B -pl :control-center-app -Pproduction -DskipTests -am install" "compile-ccapp.out" "$VERBOSE" || return 1 + runToFile "'$MVN' $D -B -pl :control-center-app -Pproduction -Ddocker.tag=local docker:build" "build-ccapp-docker.out" "$VERBOSE" || return 1 + runToFile "'$MVN' $D -B -pl :control-center-keycloak package -Ddocker.tag=local docker:build" "build-cckeycloak-docker.out" "$VERBOSE" || return 1 +} + +## Build Apps used in CC and CC itself if testing the snapshot +# $1 whether CC version is snapshot or not +buildCC() { + log -n "** Building Control Center and APPS - $VERSION $CCVERSION $1 **" + local D=$PWD + if [ -z "$SKIPBUILD" ]; then + [ "$1" != true ] || compileCC || return 1 ; cd $D + compileCCStarter || return 1 ; cd $D + compileBakery || return 1 ; cd $D + fi + [ -n "$SKIPHELM" ] || runCmd -q "Update helm dependencies" helm dependency build charts/control-center + prepareRegistry || return 1 + uploadLocalImages "$1" || return 1 + [ -z "$CCPUSH" ] || pushLocalToDockerhub next +} + + + + + + + + diff --git a/scripts/pit/lib/lib-k8s-cc.sh b/scripts/pit/lib/lib-k8s-cc.sh index 9521336..817f798 100644 --- a/scripts/pit/lib/lib-k8s-cc.sh +++ b/scripts/pit/lib/lib-k8s-cc.sh @@ -1,6 +1,7 @@ . `dirname $0`/lib/lib-utils.sh . `dirname $0`/lib/lib-playwright.sh . `dirname $0`/lib/lib-k8s-vendor.sh +. `dirname $0`/lib/lib-k8s-apps.sh ## Domain and Host Configuration CC_DOMAIN=local.alcala.org @@ -19,9 +20,7 @@ CC_NS=control-center ## UI tests to run after the control-center is installed CC_TESTS=${CC_TESTS:-cc-setup.js cc-install-apps.js cc-identity-management.js cc-localization.js} -CC_APP_REPO=bakery-app-starter-flow-spring:cc-24.7 -CC_APP_NAME=bakery-cc - +## check if docker is working checkDockerRunning() { if ! docker ps > /dev/null 2>&1; then err "!! Docker is not running. Please start Docker and try again. !!" @@ -29,44 +28,72 @@ checkDockerRunning() { fi } +## Check the appVersion of the CC helm chart in docker.io +# $1 CC tag in docker.io +checkCurrentVersion() { + [ -z "$1" -o "$1" = current ] || ARG="--version $1" + V=`helm show all oci://docker.io/vaadin/control-center $ARG 2>&1 | grep "^appVersion" | cut -d " " -f2` + [ -z "$V" ] && err "No CC version found for $1" && return 1 + [ -n "$1" -a "$1" != current -a "$1" != "$V" ] && err "Bad version found for $1 != $V" && return 1 + echo $V +} + + + +## Given a platform version check what is the corresponding CC version +# $1 platform version computeCCVersion() { [ -z "$1" ] && return git fetch --tags -q for i in `git tag | sort -r`; do local vVersion=`git show $i:pom.xml 2>/dev/null | grep '' | cut -d '>' -f2 | cut -d '<' -f1` # echo "$1 - $vVersion" >&2 - [ "$vVersion" = "$1" ] && echo $i && return 0 + [ "$vVersion" = "$1" ] && echo $i && ([ -n "$TEST" ] || log "Platform $VERSION has control-center CC $i") && return 0 done mvn help:evaluate -Dexpression=project.version -q -DforceStdout } -saveCerts() { - f1=cc-tls.crt - f2=cc-tls.key - f3=$CC_DOMAIN.pem - echo -e "$CC_CERT" > $f1 || return 1 - echo -e "$CC_KEY" > $f2 || return 1 - cat $f1 $f2 > $f3 - mkdir -p certs.out - cp $f1 $f2 $f3 certs.out/ +## Check whether the control-center chart is installed and display info +isCCInstalled() { + helm list -n control-center | grep -v "^NAME" | awk '{print " · "$9" · "$10" · "$4}' } +## If the process fails, download the logs of the apps running for inclussion in the CI artifact +downloadLogs() { + # this is run after a failure, thus always fail + hasCCNs || return 1 + H="" + for i in `kubectl get pods -n control-center | egrep -v '^NAME|^control-center' | awk '{print $1}'` + do + [ -z "$H" ] && log -n "Saving deployment and pod logs" && H=done + runToFile "kubectl logs $i -n $CC_NS" "pod-$i.out" "$VERBOSE" + done + for i in `kubectl get deployments -n control-center | egrep -v '^NAME|^control-center' | awk '{print $1}'` + do + runToFile "kubectl describe deployment $i -n $CC_NS" "deployment-$i.out" "$VERBOSE" + done + return 1 +} + + ## Install Control Center with Helm +# $1 control center version installCC() { - [ -n "$SKIPHELM" ] && H=`kubectl get pods 2>&1` && echo "$H" | egrep -q 'control-center-[0-9abcdef]+-..... ' && return 0 - [ -n "$VERBOSE" ] && D=--debug || D="" + log -n "** Installing Control Center $1 with Helm **" + [ -n "$CC_KEY" -a -n "$CC_CERT" ] && args="--set app.tlsSecret=$CC_TLS_A --set keycloak.tlsSecret=$CC_TLS_K" || args="" - [ -z "$TEST" ] && log "Installing Control Center with version: $1" + case "$1" in - *SNAPSHOT) - buildCC || return 1 - args="$args charts/control-center --set app.image.tag=local --set keycloak.image.tag=local" - ;; - current) args="$args oci://docker.io/vaadin/control-center" ;; - "") err "Unable to compute CC version for platform version '$1'" && return 1 ;; - *) args="$args oci://docker.io/vaadin/control-center --version $1" ;; + *SNAPSHOT) args="$args charts/control-center --set app.image.tag=local --set keycloak.image.tag=local" ;; + current) args="$args oci://docker.io/vaadin/control-center" ;; + "") err "Unable to compute CC version for platform version '$VERSION'" && return 1 ;; + *) args="$args oci://docker.io/vaadin/control-center --version $1" ;; esac + [ -z "$TEST" ] && log "Installing Control Center with version: $1" + [ -n "$SKIPHELM" ] && H=`kubectl get pods 2>&1` && echo "$H" | egrep -q 'control-center-[0-9abcdef]+-..... ' && return 0 + [ -n "$VERBOSE" ] && D=--debug || D="" + [ -n "$DO_REG_URL" ] && args="$args \ --set app.image.repository=$DO_REG_URL/control-center-app \ --set keycloak.image.repository=$DO_REG_URL/control-center-keycloak" @@ -115,7 +142,7 @@ waitForCC() { "") log "Control center not installed in k8s" && return 1 ;; 1/1*Running*) - echo "" && log "Control Center up and running - Status: $H" + log -n "Control Center up and running - Status: $H" return 0 ;; *) [ "$H" != "$last" ] && ([ -n "$VERBOSE" -a -n "$last" ] && echo "" || true) \ @@ -127,15 +154,22 @@ waitForCC() { done } +## check if the cluster has already the CC namespace +hasCCNs() { + H=`kubectl get ns 2>&1` + [ $? = 0 ] && echo "$H" | egrep -q "^$CC_NS " || return 1 +} + ## Uninstall control-center uninstallCC() { - H=`kubectl get ns 2>&1` - [ $? = 0 ] && echo "$H" | egrep -q "^$CC_NS " || return 0 + hasCCNs || return 0 [ -n "$VERBOSE" ] && HD=--debug && KD=--v=10 - runCmd -q "Uninstalling Control-Center" helm uninstall control-center --wait -n $CC_NS $HD + H=`isCCInstalled` && runCmd -q "Uninstalling $H" helm uninstall control-center --wait -n $CC_NS $HD runCmd -q "Removing namespace $CC_NS" kubectl delete ns $CC_NS $KD $1 } +## Display configuration and certificate for a certain ingress +# $1 ingress name getTLs() { H=`kubectl get ingress $1 -n $CC_NS -o jsonpath='{.spec.rules[0].host}'` HS=`kubectl get ingress $1 -n $CC_NS -o jsonpath='{.spec.tls[*].hosts[*]}'` @@ -145,14 +179,16 @@ getTLs() { dim " hosts: $HS cert: $C" } +## Display configuration and certificate of all ingresses checkTls() { - [ -n "$TEST" ] && return 0 + [ -n "$SKIPSETUP" -o -n "$TEST" ] && return 0 log "Checking TLS certificates for all ingresses hosted in the cluster" for i in `kubectl get ingresses -n $CC_NS | grep nginx | awk '{print $1}'`; do getTLs "$i" done } +## Reload ingress process (useful after changing a certificate) reloadIngress() { [ -n "$TEST" ] && return 0 pod=`kubectl -n $CC_NS get pods | grep control-center-ingress-nginx-controller | awk '{print $1}'` || return 1 @@ -162,15 +198,18 @@ reloadIngress() { ## Configure secrets for the control-center and the keycloak servers installTls() { - [ -n "$TEST" ] && return 0 + [ -n "$SKIPSETUP" ] && return 0 [ -z "$CC_KEY" -o -z "$CC_CERT" ] && log "No CC_KEY and CC_CERT provided, skiping TLS installation" && return 0 # [ -n "$CC_FULL" ] && CC_CERT="$CC_FULL" [ -z "$TEST" ] && log "Installing TLS $CC_TLS for $CC_CONTROL and $CC_AUTH" || cmd "## Creating TLS file '$CC_DOMAIN.pem' from envs" f1=cc-tls.crt f2=cc-tls.key f3=$CC_DOMAIN.pem + cmd 'echo -e "$CC_CERT" > '$f1 echo -e "$CC_CERT" > $f1 || return 1 + cmd 'echo -e "$CC_KEY" > '$f2 echo -e "$CC_KEY" > $f2 || return 1 + cmd "cat $f1 $f2 > $f3" cat $f1 $f2 > $f3 # remove old secrets if they exist (only needed for testing purposes since secrets are deleted before running the helm chart) @@ -197,6 +236,7 @@ installTls() { ## Show temporary user-email and password in the terminal showTemporaryPassword() { + [ -n "$SKIPSETUP" -o -n "$TEST" ] && return 0 email=`runCmd "Getting temporary admin email for Control Center" \ "kubectl -n $CC_NS get secret control-center-user -o go-template=\"{{ .data.email | base64decode | println }}\""` passw=`runCmd "Getting temporary admin password for Control Center" \ @@ -205,59 +245,38 @@ showTemporaryPassword() { } ## Run Playwright tests for the control-center +# $1 Version of CC to test +# $2 tag to use for application images +# $3 whether it is CC snapshot runPwTests() { - computeNpm [ -n "$SKIPPW" ] && return 0 + log -n "** Running tests for Apps with tag '$2' in Control Center '$1' **" + computeNpm [ -z "$CC_CERT" -o -z "$CC_KEY" ] && NO_TLS=--notls || NO_TLS="" - [ "$1" = current ] && T=latest || T=local + + [ "$3" = true ] && T=local || T="${APPVERSION:-$2}" + ## TODO: ask IT for access to vaadin docker registry for deploying bakery and bakery-cc - [ "$1" = current ] && R=k8sdemos || R=vaadin - [ "$1" != current -a "$VENDOR" = do ] && R=$DO_REG_URL && S="--secret=$DO_REGST" || S="" + S="" ; R=$REGISTRY + [ "$2" = local -a "$VENDOR" = do ] && R=$DO_REG_URL && S="--secret=$DO_REGST" for f in $CC_TESTS; do [ "$CLUSTER" == "docker-desktop" ] || stopForwardIngress && forwardIngress $CC_NS || return 1 - runPlaywrightTests "$PIT_SCR_FOLDER/its/$f" "" "$1" "control-center" --url=https://$CC_CONTROL --login=$CC_EMAIL --tag=$T --registry=$R $S $NO_TLS || return 1 + runPlaywrightTests "$PIT_SCR_FOLDER/its/$f" "" "$T" "control-center" \ + --url=https://$CC_CONTROL --login=$CC_EMAIL --version=$CCVERSION \ + --tag=$T --registry=$REGISTRY $S $NO_TLS || return 1 if [ "$f" = cc-install-apps.js ]; then reloadIngress && checkTls || return 1 fi done } -compileBakery() { - computeMvn - checkoutDemo $CC_APP_REPO:cc-24.7 || return 1 - setDemoVersion $CC_APP_REPO $VERSION >/dev/null || return 1 - runToFile "'$MVN' -ntp -B clean install -Pproduction -DskipTests" "compile-bakery-no-cc.out" "$VERBOSE" || return 1 - runCmd "Building Docker image for Bakery" docker build -t vaadin/bakery:local . || return 1 - runToFile "'$MVN' -ntp -B clean install -Pproduction,control-center -DskipTests" "compile-bakery-cc.out" "$VERBOSE" || return 1 - runCmd "Building Docker image for Bakery-CC" docker build -t vaadin/bakery-cc:local . || return 1 - cmd "cd .." ; cd .. -} - -compileCC() { - computeMvn - local D="-q -ntp" - [ -z "$VERBOSE" ] && D="-Dorg.slf4j.simpleLogger.showDateTime -Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss.SSS" - runToFile "'$MVN' $D -B -pl :control-center-app -Pproduction -DskipTests -am install" "compile-ccapp.out" "$VERBOSE" || return 1 - runToFile "'$MVN' $D -B -pl :control-center-app -Pproduction -Ddocker.tag=local docker:build" "build-ccapp-docker.out" "$VERBOSE" || return 1 - runToFile "'$MVN' $D -B -pl :control-center-keycloak package -Ddocker.tag=local docker:build" "build-cckeycloak-docker.out" "$VERBOSE" || return 1 -} - -buildCC() { - if [ -z "$SKIPBUILD" ]; then - compileBakery || return 1 - compileCC || return 1 - fi - prepareRegistry || return 1 - uploadLocalImages || return 1 - runCmd -q "Update helm dependencies" helm dependency build charts/control-center -} - ## Main method for running control center +# $1 Version of CC to test +# $2 tag to use for application images +# $3 whether it is CC snapshot runControlCenter() { - [ -z "$TEST" ] && echo "" && bold "----> Running builds and tests on app control-center version: '$1'" - [ -n "$TEST" ] && echo "" && cmd "### ------> Run PiT for: app=control-center version '$1' <------" - + log -n "----> Running PiT for app: control-center version: '$1' tag: '$2' " ## Check if port 443 is busy [ -n "$TEST" ] || checkBusyPort "443" || return 1 @@ -271,9 +290,14 @@ runControlCenter() { ## Clean up CC from a previous run unless SKIPHELM is set [ -z "$SKIPHELM" ] && uninstallCC + ## Build CC and apps + [ "$2" != local ] || buildCC "$3" || return 1 + ## Install Control Center installCC $1 || return 1 + [ -z "$TEST" ] && H=`isCCInstalled` && log "Installed Control-Center is: $H" + ## Control center takes a long time to start waitForCC 900 || return 1 @@ -284,33 +308,30 @@ runControlCenter() { installTls && checkTls || return 1 ## Run Playwright tests for the control-center - runPwTests "$1" || return 1 + runPwTests "$1" "$2" "$3" || return 1 ## Uninstall the control-center if --keep-cc is not set [ -n "$KEEPCC" ] || uninstallCC --wait=false || return 1 - [ -z "$TEST" ] && bold "----> The version '$1' of 'control-center' app was successfully built and tested." + log "----> Tested version '$1' of 'control-center'" return 0 } +## Run PiT for Control Center validateControlCenter() { checkCommands docker kubectl helm unzip || return 1 checkDockerRunning || return 1 rm -rf screenshots.out ## Run control center in current version (stable) if [ -z "$NOCURRENT" ]; then - runControlCenter current || return 1 + CCVERSION=`checkCurrentVersion $CCVERSION` || return 1 + runControlCenter $CCVERSION latest || downloadLogs || return 1 fi ## Run control center for provided version if [ "$VERSION" != "current" ]; then - runControlCenter `computeCCVersion $VERSION` || return 1 + CCVERSION=`computeCCVersion $VERSION` || return 1 + expr "$CCVERSION" : ".*SNAPSHOT" >/dev/null && H=true || H="" + runControlCenter $CCVERSION local $H || downloadLogs || return 1 fi -} - - - - - - - +} \ No newline at end of file diff --git a/scripts/pit/lib/lib-k8s-vendor.sh b/scripts/pit/lib/lib-k8s-vendor.sh index 8c9e1f3..48e9f4a 100644 --- a/scripts/pit/lib/lib-k8s-vendor.sh +++ b/scripts/pit/lib/lib-k8s-vendor.sh @@ -4,6 +4,9 @@ C_KIND_PREFIX=kind- C_DO_REGION=fra1 C_DO_PREFIX=do-${C_DO_REGION}- +## TODO: ask IT for access to vaadin docker registry for deploying bakery and bakery-cc +REGISTRY=k8sdemos + ## Check that the command has SUID bit set # $1: command hasSUID() { @@ -35,7 +38,7 @@ setSuid() { && runCmd "Changing set-uid to: $R" "sudo chmod u+s $T" && echo "$T" && return 0 } -## +## Start k8s portforward to CC ingress # $1: namespace # $2: service # $3: port in guest @@ -55,7 +58,7 @@ startPortForward() { egrep -q 'Forwarding from' "$bgf" } -## +## Stop k8s portforward # $1: service stopPortForward() { H=`getPids kubectl "port-forward service/$1"` @@ -71,17 +74,17 @@ stopForwardIngress() { stopPortForward control-center-ingress-nginx-controller } -## +## Create a new cluster in KinD # $1: cluster name createKindCluster() { checkCommands kind || return 1 - kind get clusters 2>/dev/null | grep -q "^$1$" && log "Reusing Kind cluster: '$1'" && return 0 + kind get clusters 2>/dev/null | grep -q "^$1$" && ([ -n "$TEST" ] || log "Reusing Kind cluster: '$1'") && return 0 runCmd -qf "Creating KinD cluster: $1" \ "kind create cluster --name $1" || return 1 [ -n "$KEEPCC" ] || onExit deleteKindCluster "$1" } -## +## Delete a cluster in KinD # $1: cluster name deleteKindCluster() { checkCommands kind || return 1 @@ -90,6 +93,8 @@ deleteKindCluster() { runCmd -q "Deleting Cluster $name" "kind delete cluster --name $name" || return 1 } +## Create a new cluster in DO +# $1: cluster name createDOCluster() { size=${2:-s-4vcpu-8gb} nodes=1 @@ -99,6 +104,8 @@ createDOCluster() { [ -n "$KEEPCC" ] || onExit deleteDOCluster "$1" } +## Delete a cluster in DO +# $1: cluster name deleteDOCluster() { checkCommands doctl || return 1 name=${1:-$CLUSTER} @@ -106,6 +113,9 @@ deleteDOCluster() { runCmd -q "Deleting Registry in DO" "doctl registry delete --force" } +## Create a Cluster +# $1 cluster name +# $2 vemdor type (kind, do) createCluster() { name=${1:-$CLUSTER} type=${2:-$VENDOR} @@ -117,6 +127,8 @@ createCluster() { esac } +## Delete a cluster +# $1 cluster name, if not provided it ask in stdin deleteCluster() { name=${1:-$CLUSTER} if [ -z "$name" ]; then @@ -139,6 +151,10 @@ deleteCluster() { esac } +## Set both current cluster context and default namespace for kubectl +# $1 cluster name +# $2 namespace +# $3 cluster vendor (kind, do) setClusterContext() { ns=$2 case $3 in @@ -148,13 +164,14 @@ setClusterContext() { esac H=`kubectl config get-contexts | tr '*' ' ' | awk '{print $1}' ` [ -z "$H" ] && log "Cluster $current not found in kubectl contexts" && return 1 - runCmd -q "Setting context to $current" "kubectl config use-context $current" || return 1 + runCmd -qf "Setting context to $current" "kubectl config use-context $current" || return 1 H=`kubectl config current-context` [ "$H" != "$current" ] && log "Current context is not $current" && return 1 - runCmd -q "Setting default namespace to $ns" "kubectl config set-context --current --namespace=$ns" || return 1 + runCmd -qf "Setting default namespace to $ns" "kubectl config set-context --current --namespace=$ns" || return 1 kubectl get ns >/dev/null 2>&1 || return 1 } +## Compute a unique name for the registry to create in DO computeDORegistry() { H=`doctl registry get --no-header --format Name 2>/dev/null` [ $? = 0 ] && echo "$H" && return @@ -162,6 +179,7 @@ computeDORegistry() { echo "$U" } +## Login to the private registry in DO loginDORegistry() { doctl registry get --no-header >/dev/null 2>&1 if [ $? != 0 ]; then @@ -171,21 +189,24 @@ loginDORegistry() { runCmd -q "Adding Registry to Cluster: $CLUSTER" "doctl kubernetes cluster registry add $CLUSTER" || return 1 } +## Prepare a private registry in DO for local images prepareRegistry() { [ "$VENDOR" != "do" ] && return 0 + log "Prepare registry for Vendor DO" checkCommands doctl || return 1 DO_REGST=`computeDORegistry` loginDORegistry "$DO_REGST" || return 1 DO_REG_URL="registry.digitalocean.com/$DO_REGST" } +## Patch cluster so as it can access to private DO registry for local images patchDeployment() { [ "$VENDOR" != "do" ] && return 0 checkCommands doctl || return 1 DO_REGST=`computeDORegistry` if [ "$VENDOR" = do ]; then # Not using runCmd because of issues with quotes in JSON argument - [ -n "$TEST" ] || log "Patching imagePullSecrets for DO registry $DO_REGST" + log "Patching imagePullSecrets for DO registry $DO_REGST" cmd kubectl patch serviceaccount -n $1 default -p '{"imagePullSecrets": [{"name": "'$DO_REGST'"}]}' [ -n "$TEST" ] || kubectl patch serviceaccount -n $1 default -p '{"imagePullSecrets": [{"name": "'$DO_REGST'"}]}' || return 1 cmd kubectl patch deployment control-center -n $1 --type='json' -p='[{"op": "add", "path": "/spec/template/spec/imagePullSecrets", "value":[{"name":"'$DO_REGST'"}]}]' @@ -195,20 +216,58 @@ patchDeployment() { fi } +## Upload generated local images to the vendor cluster +# $1 whether it should upload cc images as well. uploadLocalImages() { case "$VENDOR" in kind) - for i in control-center-app control-center-keycloak bakery bakery-cc; do + echo "" && log "** Loading images for vendor KinD **" + for i in bakery bakery-cc cc-starter; do + runCmd -q "Load docker image $i for Kind" \ + kind load docker-image $REGISTRY/$i:local --name "$CLUSTER" || return 1 + done + [ "$1" != true ] && return + for i in control-center-app control-center-keycloak; do runCmd -q "Load docker image $i for Kind" \ kind load docker-image vaadin/$i:local --name "$CLUSTER" || return 1 done ;; do) - for i in control-center-app control-center-keycloak bakery bakery-cc; do - runCmd -q "Tag image $i" docker tag vaadin/$i:local $DO_REG_URL/$i:local || return 1 + echo "" && log "** Loading images for vendor DO **" + for i in cbakery bakery-cc cc-starter; do + runCmd -q "Tag image $i" docker tag $REGISTRY/$i:local $DO_REG_URL/$i:local || return 1 + runCmd -q "PUSH image $i" docker push $DO_REG_URL/$i:local || return 1 + done + [ "$1" != true ] && return + for i in control-center-app control-center-keycloak; do + expr "$i" : "^control-center" >/dev/null && R=vaadin || R=$REGISTRY + runCmd -q "Tag image $i" docker tag $vaadin/$i:local $DO_REG_URL/$i:local || return 1 runCmd -q "PUSH image $i" docker push $DO_REG_URL/$i:local || return 1 done ;; *) :;; esac } + +## check if the current user has push rights in docker.io for $REPOSITORY +checkDockerPushPermissions() { + iName=$REGISTRY/foobar:latest + docker pull busybox > /dev/null 2>&1 || return 1 + docker tag busybox $iName > /dev/null 2>&1 + docker push $iName > /dev/null 2>&1 || return 1 + docker image rm $iName > /dev/null 2>&1 +} + +## push local images to central registry +## it is enabled by setting the env PUSH=true +# $1 tag (default next) +pushLocalToDockerhub() { + _tag=${1-next} + checkDockerPushPermissions || { + err "You dont have permissions to push to docker.io/$REGISTRY "; return 1 + } + for i in bakery bakery-cc cc-starter; do + runCmd -q "TAG local image as $1" docker taga $REGISTRY/i:local $REGISTRY/$i:$_tag || return 1 + runCmd -q "PUSH image $i to docker.io" docker push $REGISTRY/$i:$_tag || return 1 + done +} diff --git a/scripts/pit/lib/lib-playwright.sh b/scripts/pit/lib/lib-playwright.sh index a098b2f..847ccbf 100644 --- a/scripts/pit/lib/lib-playwright.sh +++ b/scripts/pit/lib/lib-playwright.sh @@ -39,8 +39,7 @@ runPlaywrightTests() { _args="$* --name=$_name --mode=$_mode" isHeadless && _args="$_args --headless" - [ -z "$TEST" ] && log "Running Visual-Test: $_base_name" - [ -n "$TEST" ] && cmd "## Running Visual-Test: $_base_name" + log "Running visual test: $_base_name" PATH=$PATH START=$START runToFile "'$NODE' '$_test_file' $_args" "$_pfile" "$VERBOSE" true err=$? [ -n "$TEST" ] && return 0 diff --git a/scripts/pit/lib/lib-utils.sh b/scripts/pit/lib/lib-utils.sh index c6f6837..2735086 100644 --- a/scripts/pit/lib/lib-utils.sh +++ b/scripts/pit/lib/lib-utils.sh @@ -91,6 +91,9 @@ printnl() { ## log with some nice color log() { + expr "$1" : "\-" > /dev/null && _opt=${1#-} && shift || _opt="" + [ "$_opt" = n ] && echo "" + [ -n "$TEST" ] && cmd "## $*" && return 0 _p=`computeTime` print '> ' 0 32 "$*" printnl '' 2 36 " - "`computeTime`"" @@ -626,7 +629,7 @@ changeBlock() { rm -f $$-1 [ -n "$__diff" ] && cmd "$_cmd" && __err=0 || __err=1 [ -z "$TEST" -a -n "$__diff" -a "$__val" = remove ] && warn "Remove $__left in $__bfile" - [ -z "$TEST" -a -n "$__diff" -a "$__val" != remove ] && warn "Changed '$__left' to '$__val' in $__bfile" + [ -z "$TEST" -a -n "$__diff" -a "$__val" != remove ] && warn "Changed '($__left)($__right)' to '$__val' in $__bfile" return $__err } @@ -874,7 +877,7 @@ installJDKRuntime() { setJavaPath() { H=`find "$1" -name Home -type d` [ -z "$H" ] && H="$1" - [ -z "$TEST" ] && log "Setting JAVA_HOME=$H PATH=$H/bin:\$PATH" + [ -z "$TEST" ] && log "Setting JAVA_HOME=$H PATH=$H/bin:\$PATH" [ -n "$TEST" ] && cmd "## Setting JAVA_HOME=$H PATH=$H/bin:\$PATH" [ ! -d "$H/bin" ] && return 1 cmd "export PATH=$H/bin:\$PATH JAVA_HOME=$H" @@ -996,3 +999,30 @@ computePropAfterPatch() { *) echo "vaadin.version";; esac } + +## return the version of one dependency in a maven project +# $1 groupId +# $2 artifactId +# $3 extra arguments to pass to mvn +getMvnDependencyVersion() { + [ ! -f pom.xml ] && warn "Not a maven project" && return 1 + [ -z "$MVN" ] && computeMvn + "$MVN" dependency:tree $3 | grep "$1:$2" | grep INFO | sed -e 's|.*.INFO. ||g' | cut -d : -f4 +} + +## set dependency of one specific package in pom.xml +# $1 groupId +# $2 artifactId +# $3 version +# $4 extra arguments to pass to mvn +setMvnDependencyVersion() { + expr "$3" : ".*SNAPSHOT" >/dev/null && _newVers=$3 || _newVers=`echo "$3" | tr - .` + _curVers=`getMvnDependencyVersion "$1" "$2" "$4"` || return 1 + if [ "$_curVers" != "$_newVers" ]; then + changeBlock ''$2'' '\s+' '${1}'$_newVers'${3}' pom.xml + _curVers=`getMvnDependencyVersion "$1" "$2" "$4"` || return 1 + [ "$_curVers" != "$_newVers" ] && err "CC version mismatch $_curVers != $_newVers" && return 1 + fi + log "App is using $1:$2:$_curVers" + return 0 +} \ No newline at end of file diff --git a/scripts/pit/run.sh b/scripts/pit/run.sh index d69b976..a878ed3 100755 --- a/scripts/pit/run.sh +++ b/scripts/pit/run.sh @@ -56,8 +56,8 @@ computeStarters() { ### MAIN main() { _start=$START - - [ -z "$TEST" ] && log "===================== Running PiT Tests ============================================" \ + [ -n "$TEST" ] && HEAD="Showing PiT Commands" || HEAD="Executing PiT Tests" + log "===================== $HEAD =====================================" ## Install playwright in the background (not used since there were some issues) # checkPlaywrightInstallation `computeAbsolutePath`/its/foo & @@ -87,8 +87,7 @@ main() { ## Run presets (star.vaadin.com) or archetypes for i in $presets; do - [ -z "$TEST" ] && log "================= Executing PiT Tests '$i' $OFFLINE ==================" - [ -n "$TEST" ] && echo "" && cmd "# ================= Showing PiT commands for '$i' $OFFLINE ==================" + log -n "================= $HEAD for '$i' ==================" if expr "$i" : '.*-hotswap' >/dev/null; then installJBRRuntime || continue elif [ -n "$JDK" ]; then @@ -100,8 +99,7 @@ main() { ## Run demos (proper starters in github) for i in $demos; do - [ -z "$TEST" ] && log "================= Executing PiT Tests '$i' $OFFLINE ==================" - [ -n "$TEST" ] && echo "" && cmd "# ================= Showing PiT commands for '$i' $OFFLINE ==================" + log -n "================= $HEAD for '$i' ==================" if expr $i : control-center >/dev/null; then cd "$tmp" checkoutDemo $i || return 1