Skip to content
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

Project hooks and github status hooks on cypress v5 #148

Merged
merged 6 commits into from
Oct 2, 2020

Conversation

jhicken
Copy link
Collaborator

@jhicken jhicken commented Sep 28, 2020

So this relates to...
#144
#14
#143

And has implications for #120

This introduces a new set of forms on the project edit view that allow you to setup a few types of hooks.

Webhooks: These are pretty straight forward. Every time one of the event hooks are called, json representations of the run and instance involved in the event plus some extra stats data will be sent in a POST call from sorry-cypress to url that is defined. You can also provide headers that will be passed in the post call.

Github Status Hooks: Every time a run starts, finishes or an instance finishes. The provided github repository will receive a status update with the current results and a link to the run. Currently a github personal access token with status access on the repo is required.

Screen Shot 2020-09-27 at 9 00 22 PM

github status
Screen Shot 2020-09-27 at 8 56 28 PM

This is currently for v5 but I have a non v5 version of the branch as well if we need it.

@agoldis
Copy link
Collaborator

agoldis commented Sep 29, 2020

That's 💥 will get it out soon!

@agoldis agoldis changed the base branch from master to next September 30, 2020 06:49
* origin/next:
  Use eslint
  Update dependencies, use @babel/node
Copy link
Collaborator

@agoldis agoldis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super super great 🚀💥⚡️. Thanks a lot for your great ideas and work!

  • I have changed the base for that PR to next
  • I have pushed few changes to next to put some focus on dev experience and code quality - eslint, typescript errors and prettier. Now there are more people working on that I want to keep the project clean and avoid broken windows.

As for the code / implementation:

  • Let's try to keep api and director typed, I didn't do a great job with types on dashboard and have been suffering. Please tell me is that's too much effort, I will try to help
  • Did you consider a pub/sub for communicating events in director? I am concerned by putting too much logic into routing functions.
  • I noticed few opportunities to use optional chaining.

Also, see inline comments

packages/director/package.json Outdated Show resolved Hide resolved
}

console.log(`>> Machine is joining a run`, { ciBuildId });

const response = await app.get('executionDriver').createRun(req.body);
const response = await executionDriver.createRun(req.body);
const runWithSpecs = await executionDriver.getRunWithSpecs(response.runId);
Copy link
Collaborator

@agoldis agoldis Sep 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about a pub/sub here?

pub.emit(hookEvents.RUN_START, { runId: response.runId });

The only problem is getting the execution driver, please let me know if you think that is a good option.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably personal opinion. In my early days of programming I delt with the event emmiter pattern a lot and grew a major distaste for it. Particularly when stuff goes wrong and your emitter is hooked up to multiple subscribers. Tracking down subscriber order is a massive pain. Also just putting break points and trying to debug into a subscriber is kinda succy. Since event emitters push things to the back of the call stack.

If your not using the built in event system its not as big of a deal. Cause you can follow the code flow a little better. But I generally shy away from it cause I find it more understandable to track direct function calls.

That said if you would like me to change it I still can.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it can go left when abused - there are pros and cons. I did see emitters working nicely when controlled and used strictly. I also suffered a lot while working on systems that abused the pattern and lost control of emitters / listeners.

Bottom line, if you dislike emitters so much, let's try to find a different solution. What I am looking for is to separate the functionality that deals with director primary responsibility (manage the tests) from hooks functionality.

Simply extracting all hooks functionality from app.ts into a separate module would also work for me.

Comment on lines +130 to +144
const isRunStillRunning = run.specs.reduce(
(
wasRunning: boolean,
currentSpec: {
claimed: boolean;
results: any;
},
index: number
) => {
return (
!currentSpec.claimed || !run.specsFull[index].results || wasRunning
);
},
false
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be a distinct method?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What alternative are you thinking of?

I separated it into a function for readability. If thats what you are asking about.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this

@jhicken
Copy link
Collaborator Author

jhicken commented Sep 30, 2020

I replied to everything inline.

Let's try to keep api and director typed, I didn't do a great job with types on dashboard and have been suffering. Please tell me is that's too much effort, I will try to help

Thanks! Yeah help on that would be super appreciated. Sorry if im a pain on that. I'm not a big typescript user. Im happy to make whatever changes you think we need to. So if there are places you want me to change types just call them out. Also there seems to be a lot of ways and places to define said types. Would you like them in a single file? Do you want them in the source file that is most closely related to them. Do you want them inline on functions themselfs. Do you want them in a file separate file with the same name as the file that your working on. Do we wanna be sharing them across <packages>? Sorry part of why its hard for me is that I dont think we have it nailed down when and where types are created and stored.

Guide me please.

@agoldis
Copy link
Collaborator

agoldis commented Sep 30, 2020

So if there are places you want me to change types just call them out. Also there seems to be a lot of ways and places to define said types.

  • Would you like them in a single file? No
  • Do you want them in the source file that is most closely related to them. See below
  • Do you want them inline on functions themselves. See below
  • Do you want them in a file separate file with the same name as the file that your working on. No
  • Do we wanna be sharing them across ? Ideally yes, but we don't have a good solution for that now.

I am not opinionated about that, what is important is consistency. Suggesting to mimic the current director structure.

For trivial types inline function would work (example)

For more complex types, let's have a types file that is scoped a specific domain, e.g. s3 screenshot driver has its own types example

For cross-functional shared types let's use root "types" directory.

For generated types (from GraphQL) - generated/... directory

I am marking the specific functions missing types...

import { getMongoDB, init } from '@src/lib/mongo';
import { DataSource } from 'apollo-datasource';
import uuid from 'uuid/v4';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import uuid from 'uuid/v4';
import uuid from 'uuid/v4';
import { Project } from '@src/duplicatedFromDirector/project.types';

@@ -19,6 +21,56 @@ const getSortByAggregation = (direction = 'DESC') => ({
},
});

const addHookIdsToProjectHooks = (project) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const addHookIdsToProjectHooks = (project) => {
const addHookIdsToProjectHooks = (project: Project) => {

return project;
};

const removeUnusedHookDataFromProject = (project) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const removeUnusedHookDataFromProject = (project) => {
const removeUnusedHookDataFromProject = (project: Project) => {

@@ -27,29 +79,37 @@ export class ProjectsAPI extends DataSource {
async getProjectById(id: string) {
const result = getMongoDB()
.collection('projects')
.aggregate([{
.aggregate([
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.aggregate([
.aggregate<Project>([

hookId: string;
url: string;
headers: string;
hookEvents: [string];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
hookEvents: [string];
hookEvents: string[];

export interface Project {
projectId: string;
createdAt: string;
hooks?: [Hook];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
hooks?: [Hook];
hooks?: Hook[];

hookId: string;
url: string;
headers: string;
hookEvents: [string];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
hookEvents: [string];
hookEvents: string[];

export interface Project {
projectId: string;
createdAt: string;
hooks?: [Hook];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
hooks?: [Hook];
hooks?: Hook[];

@agoldis agoldis merged commit 918e1da into next Oct 2, 2020
@agoldis agoldis deleted the project-hooks-cypress-v5 branch October 2, 2020 04:21
@jhicken
Copy link
Collaborator Author

jhicken commented Oct 2, 2020

Sweet. Would you like me to make these extra changes in another PR?

@agoldis
Copy link
Collaborator

agoldis commented Oct 2, 2020

Sweet. Would you like me to make these extra changes in another PR?

If you already done some refactoring - sure, otherwise don't waste your time :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants