diff --git a/README.md b/README.md index d02e59a..44f2358 100644 --- a/README.md +++ b/README.md @@ -106,12 +106,13 @@ docker-compose -f docker-compose.test.yml up --no-build kubernetes-mixin Build only: ``` -NOPUSH=true IMAGE_NAME=solsson/kubernetes-assert:latest ./hooks/build +NOPUSH=true IMAGE_NAME=builds-registry.ystack.svc.cluster.local/yolean/assert ./hooks/build ``` Integration test: ``` +NOPUSH=true IMAGE_NAME=solsson/kubernetes-assert:latest ./hooks/build docker volume rm kubernetes-monitoring_admin 2> /dev/null || true ./test.sh ``` diff --git a/hooks/build b/hooks/build index 0a7d85b..980ada2 100755 --- a/hooks/build +++ b/hooks/build @@ -2,6 +2,10 @@ [ -z "$DEBUG" ] || set -x set -eo pipefail +# Settings +DEFAULT_REGISTRY=builds-registry.ystack.svc.cluster.local +[ -z "$BUILDS_REGISTRY" ] && BUILDS_REGISTRY=$DEFAULT_REGISTRY + [ -z "$IMAGE_NAME" ] && echo "IMAGE_NAME is required" && exit 1; GIT_STATUS=$(git status --untracked-files=no --porcelain=v2) @@ -12,6 +16,13 @@ GIT_STATUS=$(git status --untracked-files=no --porcelain=v2) echo "------ HOOK START - BUILD -------" printenv +PREPEND_REGISTRY="" +case $IMAGE_NAME in + solsson/* ) ;; + $BUILDS_REGISTRY* ) PREPEND_REGISTRY="${BUILDS_REGISTRY}/" ;; + *) ;; +esac + function imagename { buildname=$1 case $IMAGE_NAME in @@ -26,7 +37,6 @@ docker build -t $IMAGE_NAME . CONTEXTS=" runtime-nodejs runtime-typescript -specs " PUSH="" @@ -35,8 +45,8 @@ for CONTEXT in $CONTEXTS; do CONTEXT_IMAGE_NAME=$(imagename $CONTEXT) - docker build -t $CONTEXT_IMAGE_NAME -t yolean/assert-$CONTEXT -t yolean/assert-$CONTEXT:$SOURCE_COMMIT ./$CONTEXT - PUSH="$PUSH $CONTEXT_IMAGE_NAME yolean/assert-$CONTEXT:$SOURCE_COMMIT" + docker build -t $CONTEXT_IMAGE_NAME -t yolean/assert-$CONTEXT -t ${PREPEND_REGISTRY}yolean/assert-$CONTEXT:$SOURCE_COMMIT ./$CONTEXT + PUSH="$PUSH $CONTEXT_IMAGE_NAME ${PREPEND_REGISTRY}yolean/assert-$CONTEXT:$SOURCE_COMMIT" done diff --git a/runtime-nodejs/jest.kubernetes-assertions-reporter.js b/runtime-nodejs/jest.kubernetes-assertions-reporter.js index df74a08..0a3f75e 100644 --- a/runtime-nodejs/jest.kubernetes-assertions-reporter.js +++ b/runtime-nodejs/jest.kubernetes-assertions-reporter.js @@ -2,11 +2,11 @@ const fs = require('fs'); const http = require('http'); const PORT = process.env.PORT ? parseInt(process.env.PORT) : 9091; -const RERUN_WAIT = parseInt(process.env.RERUN_WAIT); const ASSERT_IS_DEV = process.env.ASSERT_IS_DEV === 'true'; const client = require('prom-client'); const register = client.register; +let allow_modification = false; const assertions_failed = new client.Gauge({ name: 'assertions_failed', @@ -52,14 +52,17 @@ class SpecFilesTracker { pathSeen(path, { numFailingTests }) { if (this._pathsSeen.hasOwnProperty(path)) { const delta = numFailingTests - this._pathsSeen[path].numFailingTests; - if (delta > 0) assertions_failed.inc(delta); - if (delta < 0) assertions_failed.dec(-delta); + if(allow_modification) { + if (delta > 0) assertions_failed.inc(delta); + if (delta < 0) assertions_failed.dec(-delta); + } } else { this._pathsSeen[path] = {}; assert_files_seen.inc(); if (numFailingTests > 0) assertions_failed.inc(numFailingTests); console.log('Path reported for the first time:', path); } + this._pathsSeen[path].numFailingTests = numFailingTests; } @@ -71,6 +74,10 @@ class SpecFilesTracker { }); } + allowMod() { + allow_modification = true; + } + modifyAll() { const modify = this.modify.bind(this); const paths = Object.keys(this._pathsSeen); @@ -80,7 +87,6 @@ class SpecFilesTracker { modify(path); }); } - } const tracker = new SpecFilesTracker(); @@ -97,31 +103,43 @@ const tracker = new SpecFilesTracker(); * We rerun all tests, not only failed, because when it comes to infra things go up and down. */ class Reruns { - - constructor({ tracker, intervalMs }) { - console.log('Activating reruns with interval (ms)', intervalMs); - this._intervalMs = intervalMs; + constructor({ tracker }) { + this._rerunTime = 0; + if (fs.existsSync('./env.json')) { + this._rerunTime = Number(JSON.parse(fs.readFileSync('./env.json', 'utf8')).RERUN_TIME); + } + if (this._rerunTime != 0) { + console.log('Activating reruns with interval (ms)', this._rerunTime * 1000); + } else { + console.log('Interval reruns are turned off. Reruns will be run until all tests are OK'); + } + setTimeout(() => { + tracker.allowMod(); + }, 9000); + this._intervalMs = this._rerunTime === 0 ? 10000 : this._rerunTime * 1000; this._timeout = null; } onRunComplete() { this._timeout !== null && clearTimeout(this._timeout); - if (!ASSERT_IS_DEV && RERUN_WAIT) { + + if (!ASSERT_IS_DEV && (this._rerunTime > 0)) { + this._timeout = setTimeout(() => { + tracker.modifyAll(); + }, this._intervalMs); + } else if (assertions_failed.hashMap[''].value > 0) { this._timeout = setTimeout(() => { tracker.modifyAll(); }, this._intervalMs); } } - } const reruns = new Reruns({ - tracker, - intervalMs: RERUN_WAIT * 1000 + tracker }); class MetricsServer { - constructor({ port, getMetrics }) { this.port = port; this.getMetrics = getMetrics; @@ -157,7 +175,6 @@ class MetricsServer { stop() { this.server.close(); } - } const server = new MetricsServer({ @@ -167,8 +184,9 @@ const server = new MetricsServer({ server.start(); -class MetricsReporter { + +class MetricsReporter { constructor(globalConfig, options) { this._globalConfig = globalConfig; this._options = options; @@ -179,7 +197,7 @@ class MetricsReporter { onRunStart() { //console.log('onRunStart', arguments); } - + onTestStart() { //console.log('onTestStart', arguments); } @@ -187,22 +205,24 @@ class MetricsReporter { onRunComplete(contexts, results) { //console.log('onRunComplete', contexts, results); const { testResults } = results; + for (let i = 0; i < testResults.length; i++) { const { testFilePath, numFailingTests } = testResults[i]; this._tracker.pathSeen(testFilePath, { numFailingTests }); } + test_suites_run.set(results.numTotalTestSuites); test_suites_run_total.inc(results.numTotalTestSuites); tests_run.set(results.numTotalTests); tests_run_total.inc(results.numTotalTests); assertions_failed_total.inc(results.numFailedTests); + if (!this._globalConfig.watch && !this._globalConfig.watchAll) { //console.log('Not a watch run. Exiting'); server.stop(); } reruns.onRunComplete(); } - } module.exports = MetricsReporter; diff --git a/runtime-nodejs/kustomize-with-rbac/kustomization.yaml b/runtime-nodejs/kustomize-with-rbac/kustomization.yaml new file mode 100644 index 0000000..bc6a33e --- /dev/null +++ b/runtime-nodejs/kustomize-with-rbac/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +bases: +- ../rbac-readonly +- ../kustomize +patchesStrategicMerge: +- specs-serviceaccount.yaml diff --git a/runtime-nodejs/kustomize-with-rbac/specs-serviceaccount.yaml b/runtime-nodejs/kustomize-with-rbac/specs-serviceaccount.yaml new file mode 100644 index 0000000..55952d1 --- /dev/null +++ b/runtime-nodejs/kustomize-with-rbac/specs-serviceaccount.yaml @@ -0,0 +1,8 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: specs +spec: + template: + spec: + serviceAccountName: assert diff --git a/runtime-nodejs/kustomize/kustomization.yaml b/runtime-nodejs/kustomize/kustomization.yaml index a6162d1..d3e8f9f 100644 --- a/runtime-nodejs/kustomize/kustomization.yaml +++ b/runtime-nodejs/kustomize/kustomization.yaml @@ -1,7 +1,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -bases: -- ../rbac-readonly resources: - scrapeable-deployment.yaml # TODO if many tests reuse this base, how do we manage podmonitor? diff --git a/runtime-nodejs/kustomize/scrapeable-deployment.yaml b/runtime-nodejs/kustomize/scrapeable-deployment.yaml index 496a334..6878aba 100644 --- a/runtime-nodejs/kustomize/scrapeable-deployment.yaml +++ b/runtime-nodejs/kustomize/scrapeable-deployment.yaml @@ -12,7 +12,6 @@ spec: labels: kubernetes-assert: metrics spec: - serviceAccountName: assert containers: - name: specs # We can't have a tag here because https://kubectl.docs.kubernetes.io/pages/reference/kustomize.html#images won't unset it, and Skaffold required no-tag URLs for build @@ -38,11 +37,6 @@ spec: valueFrom: fieldRef: fieldPath: spec.serviceAccountName - - name: ASSERT_IS_DEV - valueFrom: - fieldRef: - # This will be true for run --tail as well but that's also a dev-loop use case - fieldPath: metadata.labels['skaffold.dev/tail'] ports: - containerPort: 9091 name: assert diff --git a/specs/Dockerfile b/specs/Dockerfile deleted file mode 100644 index c9140c3..0000000 --- a/specs/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM yolean/assert-runtime-nodejs - -WORKDIR /usr/src/specs - -# When we add dependencies -#COPY --chown=nonroot:nogroup package*.json ./ -#RUN npm ci --ignore-scripts - -COPY --chown=nonroot:nogroup . . diff --git a/specs/skaffold.yaml b/specs/skaffold.yaml index 8372f5c..2681b25 100644 --- a/specs/skaffold.yaml +++ b/specs/skaffold.yaml @@ -1,4 +1,4 @@ -apiVersion: skaffold/v2beta4 +apiVersion: skaffold/v2beta15 kind: Config metadata: name: assert-specs @@ -7,13 +7,16 @@ build: gitCommit: variant: CommitSha artifacts: - - image: builds-registry.ystack.svc.cluster.local:80/yolean/assert-specs + - image: builds-registry.ystack.svc.cluster.local/yolean/assert-specs + context: ./ + custom: + buildCommand: >- + y-build-like-sync + builds-registry.ystack.svc.cluster.local/yolean/assert-runtime-nodejs:../../kubernetes-assert/runtime-nodejs sync: manual: - src: '**' dest: /usr/src/specs - kaniko: - reproducible: true cluster: {} deploy: kustomize: {}