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

Skip Checks API neutral state #278

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Conversation

yamachu
Copy link
Member

@yamachu yamachu commented Nov 15, 2021

We use CircleCI for CI.
Recently it will returns a neutral state before state is determined by the CI.
In the current code, except for success, it is designed to be considered a failure.

if info.Status != "success" {

I thought it would be better to skip the decision for neutral, which cannot be determined as success or failure, so I added that process.

スクリーンショット 2021-11-15 18 51 04

Webhook payload

{
  "action": "completed",
  "check_suite": {
    "id":,
    "node_id": "",
    "head_branch": "master",
    "head_sha": "",
    "status": "completed", <- completed???? test is running...
    "conclusion": "neutral", <- 
    "url": "",
    "before": "",
    "after": "",
    "pull_requests": [

    ],
   ...
}

… process is skipped

For example, CircleCI may often send it
@@ -183,6 +183,11 @@ func mergeSucceedItem(
return true
}

if info.Status == "neutral" {
Copy link
Contributor

Choose a reason for hiding this comment

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

I just knew conclusion field now....

I think we should define StateChangeInfo.Conclusion and check it at here.

By #261, we fill StateChangeInfo.Status in two way:

But github.StatusEvent.Status and github.StatusEvent.Conclusion are different field. It's time to stop to mix them into single field. Let's handle them separately.

Copy link
Member Author

Choose a reason for hiding this comment

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

github.StatusEvent.Status and github.StatusEvent.Conclusion are different field. It's time to stop to mix them into single field.

Yes, from code design point of view, that's a good idea.
However, some refactoring is considered necessary.

BTY, I'm sorry to postpone the issue, but how about the following changes.

- NotHandle                 bool
+ InProgress                 bool
- NotHandle:                 *ev.CheckSuite.Status != "completed",
+ InProgress:                 *ev.CheckSuite.Status != "completed" || *ev.CheckSuite.Conclusion == "neutral"

Copy link
Contributor

Choose a reason for hiding this comment

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

@yamachu

Even though, I suspect it's better to add StateChangeInfo.InProgress() method instead of your proposed approach.
It's nice abstraction to push something into the appropriate method. I think that changing struct field as your proposed is not robustness for the future.

Then we would need to change to hold values of github.StatusEvent.Status and github.StatusEvent.Conclusion in StateChangeInfo. This requires a similar refactoring as I told the above.

@@ -20,6 +20,7 @@ type StateChangeInfo struct {
ID int64
SHA string
IsRelatedToAutoBranchBody func(string) bool
IsInProgress func() bool
Copy link
Contributor

Choose a reason for hiding this comment

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

@yamachu I imagined the following code instead of passing a function to .IsInProgress field.

type StateChangeInfo struct {
+    Conclusion string
}

+func IsInProgress(s *StateChangeInfo) bool {
+  ....
+}

What do you think about this? Are there any problem to implement?

Copy link
Member Author

Choose a reason for hiding this comment

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

@tetsuharuohzeki In the code you were suggesting, did you imagine to set the Conclusion field to ev.State when received a StatusAPI event?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes.

Ah, but github.StatusEvent does not have Conclusion field. I think we can use *string for StateChangeInfo.Conclusion

Copy link
Contributor

Choose a reason for hiding this comment

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

@yamachu

Ah, but github.StatusEvent does not have Conclusion field. I think we can use *string for StateChangeInfo.Conclusion

I wrote that but I also seem your proposed code would also be nice approach which uses func.
You can choose the final implementation. How do you think?

Copy link
Member Author

@yamachu yamachu Nov 25, 2021

Choose a reason for hiding this comment

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

It's a different types, but I think I can express it in a function like TypeScript's Union type, so I'll add a Conclusion *string parameter.

In the following comments, would such an implementation be appropriate?
https://github.com/voyagegroup/popuko/pull/278/files#r754050176

func isStatusDetermined(info StateChangeInfo) bool {
	// Status API
	if info.Conclusion == nil {
		return true // or info.Status != "pending"
	}

	// Checks API
	return *info.Conclusion != "neutral"
}

func isStatusSuccess(info StateChangeInfo) bool {
	// Status API
	if info.Conclusion == nil {
		return info.Status == "success"
	}

	// Checks API
	return *info.Conclusion == "success"
}

Copy link
Contributor

Choose a reason for hiding this comment

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

@yamachu

Umm, I agree that we would need to define a status by something.

However, from your proposed psuedo code, I think the current design is wrong to handle these status.
Your proposed one mixes handling Status API and Checks API in the same code path. This makes a thing more complex.

I think we would require these refactoring to introduce this PR change cleanly:

  1. Introduce interface type which abstracts StateChangeInfo, and separate a code path into for Status API and Checks API.
  2. Do something which we would like to do in this pull request.

Copy link
Member Author

Choose a reason for hiding this comment

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

私は英語ネイティブではないため、コメントに対してコストがかかってしまっています。
そのためコメントを日本語で記載いたします。


異なる概念であるStatus APIのEventとChecks APIのEventを同一の構造体で表現していることで複雑になっていることは同意いたします。
例えば info.Status で表現されている内容が、ChecksAPIの場合はConclusionの値であるといった例です。

そのためコードパスを分離することは確かに良いように思われます。
Event依存の構造体に非依存の構造体を入れ込み、Event依存のコードパスを分離することでまずは表現可能だと考え、以下のコミットで表現してみました。
1769fde

非依存の構造体に例えば IsRelatedToAutoBranchBody のように、関数を返す形にすることで

log.Println("info: the status event is related to auto branch.")

info.mergeSucceedItem(ctx, client, info.Owner, info.Name, repoInfo, q)

q.RemoveActive()

の様にエントリポイントである checkAutoBranch は共通化出来そうではありますが、この構造体に持たせるのは違和感がありました。
そのため横に別名で生やすことで、コードの分離を実現しています。

@@ -183,6 +198,11 @@ func mergeSucceedItem(
return true
}

if info.IsInProgress() {
log.Printf("info: Check is in progres\n")
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: progress?


func inProgressWithCheckSuiteEvent(ev *github.CheckSuiteEvent) func() bool {
return func() bool {
return *ev.CheckSuite.Status != "completed" || *ev.CheckSuite.Conclusion == "neutral"
Copy link
Contributor

Choose a reason for hiding this comment

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

@yamachu

As your comment, I feel *ev.CheckSuite.Conclusion == "neutral" does not mean in progress state directly.

But this code will check whether *ev.CheckSuite.Conclusion is neutral after if *ev.CheckSuite.Status != "completed" equals to that *ev.CheckSuite.Status indicates some stopped states.

I concern that this function will return true in almost case. Is this right?

Copy link
Member Author

Choose a reason for hiding this comment

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

I concern that this function will return true in almost case. Is this right?

Yes, it enforces the order of use, which doesn't seem to be a good function...
Rather, what should be expressed is not whether it is in progress or not, but whether the state is determined or not.

@tetsuharuohzeki
Copy link
Contributor

@yamachu Sorry, I might not be able to reply soon....

Copy link
Contributor

@tetsuharuohzeki tetsuharuohzeki left a comment

Choose a reason for hiding this comment

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

@yamachu

Thank you for your patience. I seem your new changesets are nice.

Probably, you may want to squash these commits or reorganize commits. But I feel other points are no problems and ready to merge nearly.

@@ -11,8 +11,8 @@ import (
"github.com/voyagegroup/popuko/setting"
)

// FIXME: Name
Copy link
Contributor

Choose a reason for hiding this comment

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

@yamachu Would you fix this comment before merging this?

@tetsuharuohzeki
Copy link
Contributor

@yamachu Do you still face this problem?

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.

2 participants