Skip to content

Commit

Permalink
[testnet] Fix a woopsie in loadtest.yaml
Browse files Browse the repository at this point in the history
There was a hanging end, a recent change removed a conditional without testing

Test Plan: this was blocking devnet release, so i unblock devnet release

We really need better automated testing around this
  • Loading branch information
perryjrandall committed Sep 12, 2022
1 parent 659c4e6 commit 9da5e4d
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 50 deletions.
45 changes: 0 additions & 45 deletions .github/workflows/forge-unittests.yaml

This file was deleted.

41 changes: 41 additions & 0 deletions .github/workflows/helm-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "Lint Helm Charts"

on:
workflow_call:
inputs:
GIT_SHA:
required: true
type: string

jobs:
helm-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.GIT_SHA }}
# Get enough commits to compare to
fetch-depth: 100

- name: Get changed files
id: changed-files
uses: tj-actions/[email protected]

- name: Setup Python
uses: actions/setup-python@v4

- name: Install Python Dependencies
run: pip install -r testsuite/requirements.txt

- name: Should run lint
run: >
python testsuite/determinator.py
changed-files
--github-output-key SHOULD_RUN
--pattern 'terraform/helm/.*'
${{ steps.changed-files.outputs.all_changed_files }}
id: should-run-tests

- name: Run Helm Lint
if: steps.should-run-tests.outputs.SHOULD_RUN == 'true'
run: python testsuite/lint.py helm terraform/helm/*
11 changes: 8 additions & 3 deletions .github/workflows/lint-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,12 @@ jobs:
!/tmp/.tmp*/**/db/
retention-days: 1

forge-unittests:
uses: ./.github/workflows/forge-unittests.yaml
python-unit-test:
uses: ./.github/workflows/python-unit-test.yaml
with:
GIT_SHA: ${{ inputs.GIT_SHA }}
GIT_SHA: ${{ github.ref || github.sha }}

helm-lint:
uses: ./.github/workflows/helm-lint.yaml
with:
GIT_SHA: ${{ github.ref || github.sha }}
41 changes: 41 additions & 0 deletions .github/workflows/python-unit-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "Run Python Tests"

on:
workflow_call:
inputs:
GIT_SHA:
required: true
type: string

jobs:
python-unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.GIT_SHA }}
# Get enough commits to compare to
fetch-depth: 100

- name: Get changed files
id: changed-files
uses: tj-actions/[email protected]

- name: Setup Python
uses: actions/setup-python@v4

- name: Install Python Dependencies
run: pip install -r testsuite/requirements.txt

- name: Should run tests
run: >
python testsuite/determinator.py
changed-files
--github-output-key SHOULD_RUN
--pattern 'testsuite/.*py'
${{ steps.changed-files.outputs.all_changed_files }}
id: should-run-tests

- name: Run python unit tests
if: steps.should-run-tests.outputs.SHOULD_RUN == 'true'
run: python -m unittest testsuite/*test*.py
8 changes: 8 additions & 0 deletions testsuite/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import os
import sys


path = os.path.dirname(__file__)

if path not in sys.path:
sys.path.append(path)
111 changes: 111 additions & 0 deletions testsuite/determinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Generic, Optional, Sequence, Tuple, TypeVar, TypedDict

import click


@dataclass
class Verdict:
verdict: bool
reason: str
subverdicts: Sequence[Verdict]

def format(self, indent=0) -> str:
return "\n".join([
(indent * " ") + ("PASS" if self.verdict else "FAIL") + f"ED because {self.reason}",
] + [
verdict.format(indent+1) for verdict in self.subverdicts
])


TEvaluationContext = TypeVar("TEvaluationContext")


class Predicate(Generic[TEvaluationContext]):
def evaluate(self, context: TEvaluationContext) -> Verdict:
raise NotImplementedError()


@dataclass
class OrPredicate(Predicate[TEvaluationContext]):
left: Predicate[TEvaluationContext]
right: Predicate[TEvaluationContext]

def evaluate(self, context: TEvaluationContext) -> Verdict:
leftval = self.left.evaluate(context)
rightval = self.right.evaluate(context)
return Verdict(
leftval.verdict or rightval.verdict,
f"({leftval.reason}) or ({rightval.reason})",
[leftval, rightval],
)


class ChangedFilesContext(TypedDict):
changed_files: Sequence[str]


@dataclass
class ChangedFilesPredicate(Predicate[ChangedFilesContext]):
patterns: Sequence[str]

def evaluate(self, context: ChangedFilesContext) -> Verdict:
matches = []
for path in context["changed_files"]:
for pattern in self.patterns:
if re.match(pattern, path):
matches.append(path)
return Verdict(
bool(matches),
f"Matched files: {matches}",
[],
)


@click.group()
def main() -> None:
pass


@dataclass
class GithubOutput:
key: str
value: str

def format(self) -> str:
return f"::set-output name={self.key}::{self.value}"


@main.command()
@click.option("--pattern", "patterns", multiple=True)
@click.option("--github-output-key")
@click.argument("changed_files", nargs=-1)
def changed_files(
patterns: Tuple[str],
github_output_key: Optional[str],
changed_files: Tuple[str],
) -> None:
context: ChangedFilesContext = {
"changed_files": changed_files,
}
predicate = ChangedFilesPredicate(patterns)
verdict = predicate.evaluate(context)

print(verdict.format())

if github_output_key:
output = GithubOutput(
github_output_key,
"true" if verdict.verdict else "false"
)
print(output.format())
else:
if not verdict.verdict:
raise SystemExit(1)


if __name__ == "__main__":
main()
62 changes: 62 additions & 0 deletions testsuite/determinator_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest

from click.testing import CliRunner
from determinator import main, ChangedFilesPredicate, ChangedFilesContext


class ChangedFilesPredicateTestCase(unittest.TestCase):
def test_changed_files_passes(self) -> None:
context: ChangedFilesContext = {
"changed_files": ["asdf"]
}
predicate = ChangedFilesPredicate(["a.*f"])
verdict = predicate.evaluate(context)
self.assertTrue(verdict.verdict, verdict.reason)

def test_changed_files_fails(self) -> None:
context: ChangedFilesContext = {
"changed_files": ["asdf"]
}
predicate = ChangedFilesPredicate(["fdas"])
verdict = predicate.evaluate(context)
self.assertFalse(verdict.verdict, verdict.reason)


class DeterminatorTestCase(unittest.TestCase):
def test_determinator_from_github(self) -> None:
runner = CliRunner()
result = runner.invoke(
main,
[
"changed-files",
"--github-output-key", "BANANA",
"testsuite/fixtures/helm"
],
catch_exceptions=False
)
self.assertEqual(
result.output,
"FAILED because Matched files: []\n"
"::set-output name=BANANA::false\n"
)
self.assertEqual(result.exit_code, 0)

def test_determinator_from_github_passes(self) -> None:
runner = CliRunner()
result = runner.invoke(
main,
[
"changed-files",
"--pattern", ".*/.*.ts",
"--github-output-key", "BANANA",
"testsuite/fixtures/helm/banana.ts",
],
catch_exceptions=False
)
self.assertEqual(
result.output,
"PASSED because Matched files: "
"['testsuite/fixtures/helm/banana.ts']\n"
"::set-output name=BANANA::true\n"
)
self.assertEqual(result.exit_code, 0)
4 changes: 2 additions & 2 deletions testsuite/forge_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from typing import Any, Dict, List, Optional, Protocol, Sequence, Union
from unittest.mock import patch

from . import forge
from .forge import (
import forge
from forge import (
FakeTime,
ForgeCluster,
ForgeFormatter,
Expand Down
38 changes: 38 additions & 0 deletions testsuite/lint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from forge import LocalShell

import re
from typing import Tuple
from pathlib import Path

import click



@click.group()
def main() -> None:
pass


@main.command()
@click.argument("paths", nargs=-1)
def helm(paths: Tuple[str]) -> None:
shell = LocalShell(True)

error = False
for path in paths:
result = shell.run(["helm", "lint", path])
for line in result.output.decode().splitlines():
if line.startswith("[ERROR]"):
match = re.match(r".ERROR. (?P<section>[^:]+?): (?P<error_type>.*) at [(](?P<filename>.*):(?P<line>\d+)[)]: (?P<message>.*)", line)
if match:
fullpath = Path(path).parent / match.group("filename")
print("::error file={fullpath},line={line},col=1::{message}".format(fullpath=fullpath, **match.groupdict()))
error = True

if error:
raise SystemExit(1)



if __name__ == "__main__":
main()
Loading

0 comments on commit 9da5e4d

Please sign in to comment.