Skip to content

Commit

Permalink
e2e test for dbos-demo-apps (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
CaspianA1 authored Jul 1, 2024
1 parent 50ce007 commit 209a0f5
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 545 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
run: |
npm install
npm test
bash e2e_test.sh
env:
NPM_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
SILENCE_LOGS: true
33 changes: 23 additions & 10 deletions dbos-rules.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { TypeChecker } from "typescript";
import * as tslintPlugin from "@typescript-eslint/eslint-plugin";
import { ESLintUtils, TSESLint, TSESTree, ParserServicesWithTypeInformation } from "@typescript-eslint/utils";

import {
createWrappedNode, Node, FunctionDeclaration,
ts, createWrappedNode, Node, FunctionDeclaration,
CallExpression, ConstructorDeclaration, ClassDeclaration,
MethodDeclaration
} from "ts-morph";
Expand All @@ -15,6 +14,12 @@ const noSecrets = require("eslint-plugin-no-secrets");
type EslintNode = TSESTree.Node;
type EslintContext = TSESLint.RuleContext<string, unknown[]>;

/*
Note for upgrading `ts-morph` and `typescript` in `package.json`:
1. Make sure that the supported TypeScript version for `ts-morph` is the one installed here.
2. Make sure that the installed TypeScript version works with `dbos-demo-apps` (TypeScript 5.5 + ts-morph 23.0 caused some breakage there).
*/

//////////////////////////////////////////////////////////////////////////////////////////////////// Here is my `ts-morph` linting code:

////////// These are some shared types and values used throughout the code
Expand All @@ -25,7 +30,7 @@ type FunctionOrMethod = FunctionDeclaration | MethodDeclaration | ConstructorDec
// This returns `undefined` if there is no error message to emit; otherwise, it returns a key to the `ERROR_MESSAGES` map
type DetChecker = (node: Node, fn: FunctionOrMethod, isLocal: (name: string) => boolean) => string | undefined;

type GlobalTools = {eslintContext: EslintContext, parserServices: ParserServicesWithTypeInformation, typeChecker: TypeChecker};
type GlobalTools = {eslintContext: EslintContext, parserServices: ParserServicesWithTypeInformation, typeChecker: ts.TypeChecker};
let GLOBAL_TOOLS: GlobalTools | undefined = undefined;

// These included `Transaction` and `TransactionContext` respectively before!
Expand Down Expand Up @@ -114,8 +119,16 @@ function functionShouldBeDeterministic(fnDecl: FunctionOrMethod): boolean {

// Bijectivity is preseved for TSMorph <-> TSC <-> ESTree, as far as I can tell!
function makeTsMorphNode(eslintNode: EslintNode): Node {
const compilerNode = GLOBAL_TOOLS!.parserServices.esTreeNodeToTSNodeMap.get(eslintNode);
return createWrappedNode(compilerNode);
const parserServices = GLOBAL_TOOLS!.parserServices;
const compilerNode = parserServices.esTreeNodeToTSNodeMap.get(eslintNode);

const options = {
compilerOptions: parserServices.program.getCompilerOptions(),
sourceFile: compilerNode.getSourceFile(),
typeChecker: GLOBAL_TOOLS!.typeChecker
};

return createWrappedNode(compilerNode, options);
}

function makeEslintNode(tsMorphNode: Node): EslintNode {
Expand Down Expand Up @@ -325,7 +338,7 @@ function analyzeFunctionForDeterminism(fn: FunctionOrMethod) {
////////// This is the entrypoint for running the determinism analysis with `ts-morph`

function analyzeRootNodeForDeterminism(eslintNode: EslintNode, eslintContext: EslintContext) {
const parserServices = ESLintUtils.getParserServices(eslintContext);
const parserServices = ESLintUtils.getParserServices(eslintContext, false);

GLOBAL_TOOLS = {
eslintContext: eslintContext,
Expand All @@ -336,12 +349,12 @@ function analyzeRootNodeForDeterminism(eslintNode: EslintNode, eslintContext: Es
const tsMorphNode = makeTsMorphNode(eslintNode);

try {
if (Node.isSourceFile(tsMorphNode)) {
if (Node.isStatemented(tsMorphNode)) {
tsMorphNode.getFunctions().forEach(analyzeFunctionForDeterminism);
tsMorphNode.getClasses().forEach(analyzeClassForDeterminism);
}
else {
throw new Error("Was expecting a source file to be passed to `analyzeSourceNodeForDeterminism`!");
throw new Error(`Was expecting a statemented node! Got this kind instead: ${tsMorphNode.getKindName()}`);
}
}
finally {
Expand All @@ -367,7 +380,7 @@ const baseConfig = {
"no-secrets"
],

env: { "node" : true },
env: { "node": true },

rules: {
"no-eval": "error",
Expand Down Expand Up @@ -419,7 +432,7 @@ const extConfig = {
module.exports = {
meta: {
name: "@dbos-inc/eslint-plugin",
version: "1.0.3"
version: "1.0.4"
},

rules: {
Expand Down
78 changes: 78 additions & 0 deletions e2e_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
set -ex

log() {
echo -e "\n>>>>> $1\n"
}

####################################################################################################

# This list should be extended as more demos are written!
directories=(
bank/bank-backend
# bank/bank-frontend

e-commerce/payment-backend
e-commerce/shop-backend
e-commerce/shop-frontend

greeting-emails
shop-guide
tpcc
widget-store
yky-social
)

orig_dir="$PWD"
demo_apps_dir="dbos-demo-apps"
all_lints_succeeded=true

plugin_version=$(jq -r '.version' package.json)
tarball_name="dbos-inc-eslint-plugin-$plugin_version.tgz"
tarball_path="$orig_dir/$tarball_name"

####################################################################################################

prepare_demo_apps_dir() {
if [[ -d "$demo_apps_dir" ]]; then
# This is here so that running the test locally won't involve a re-clone
cd "$demo_apps_dir"
git restore . # Removing any changes made
git pull # Pulling the latest changes
cd ..
else
git clone "https://github.com/dbos-inc/$demo_apps_dir"
fi
}

tsc
npm pack
prepare_demo_apps_dir

for directory in "${directories[@]}"; do
cd "$demo_apps_dir/$directory"
cp "$tarball_path" .
npm install "$tarball_name"

# Turning off error checking temporarily
set +e
npm run lint
lint_result="$?"
set -e

if [[ "$lint_result" -ne 0 ]]; then
all_lints_succeeded=false
fi

log "Exit code for linting '$directory': $lint_result"

cd "$orig_dir"
done

log "Finished the e2e test"

if [[ "$all_lints_succeeded" = false ]]; then
exit 1
fi

####################################################################################################
Loading

0 comments on commit 209a0f5

Please sign in to comment.