Skip to content

Iterations on the Developer Experience for writing specs #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
Expand Down
16 changes: 13 additions & 3 deletions hooks/build
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -26,7 +37,6 @@ docker build -t $IMAGE_NAME .
CONTEXTS="
runtime-nodejs
runtime-typescript
specs
"

PUSH=""
Expand All @@ -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

Expand Down
54 changes: 37 additions & 17 deletions runtime-nodejs/jest.kubernetes-assertions-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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;
}

Expand All @@ -71,6 +74,10 @@ class SpecFilesTracker {
});
}

allowMod() {
allow_modification = true;
}

modifyAll() {
const modify = this.modify.bind(this);
const paths = Object.keys(this._pathsSeen);
Expand All @@ -80,7 +87,6 @@ class SpecFilesTracker {
modify(path);
});
}

}

const tracker = new SpecFilesTracker();
Expand All @@ -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;
Expand Down Expand Up @@ -157,7 +175,6 @@ class MetricsServer {
stop() {
this.server.close();
}

}

const server = new MetricsServer({
Expand All @@ -167,8 +184,9 @@ const server = new MetricsServer({

server.start();

class MetricsReporter {


class MetricsReporter {
constructor(globalConfig, options) {
this._globalConfig = globalConfig;
this._options = options;
Expand All @@ -179,30 +197,32 @@ class MetricsReporter {
onRunStart() {
//console.log('onRunStart', arguments);
}

onTestStart() {
//console.log('onTestStart', arguments);
}

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;
7 changes: 7 additions & 0 deletions runtime-nodejs/kustomize-with-rbac/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../rbac-readonly
- ../kustomize
patchesStrategicMerge:
- specs-serviceaccount.yaml
8 changes: 8 additions & 0 deletions runtime-nodejs/kustomize-with-rbac/specs-serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: specs
spec:
template:
spec:
serviceAccountName: assert
2 changes: 0 additions & 2 deletions runtime-nodejs/kustomize/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -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?
Expand Down
6 changes: 0 additions & 6 deletions runtime-nodejs/kustomize/scrapeable-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
9 changes: 0 additions & 9 deletions specs/Dockerfile

This file was deleted.

11 changes: 7 additions & 4 deletions specs/skaffold.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: skaffold/v2beta4
apiVersion: skaffold/v2beta15
kind: Config
metadata:
name: assert-specs
Expand All @@ -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: {}