Add more triggers for autoflow
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Currently, we only run the workflows when the issue is updated (please see the video below: you will see that workflowready for development label is assigned instantly because we triggered issue_updated with the milestone set but workflowin dev is not applied until we manually trigger the issue update with changing an assignee).
It would be great to trigger issue_updated event (for demo purposes) also whenever we apply changes to the related MR. Alternatively, we could create a new event (related_mr_updated?) and start the workflow when it's triggered.
Setting the environment up
-
brew install temporalto install the Temporal CLI. -
temporal server start-devto run the dev server. -
Go to http://127.0.0.1:8233/namespaces/default/workflows to see the server’s UI and workflows
-
In GDK check out
ash2k/autoflow-from-natalia(prevntepluhina/autoflow)branch ingitlabdirectory. -
In GDK check out
ash2k/autoflowbranch ingitlab-k8s-agentdirectory. -
In GDK directory open
gitlab-k8s-agent-config.ymland add:automation: temporal: host_port: "localhost:7233"
Start the GDK. Do not reconfigure it as this will undo the above changes.
Edit .gitlab/flow.py in any project in your GDK GitLab instance.
Example code for flow.py
AUTH_TOKEN = "Bearer <your-token>"
def check_status(resp, expected_status_code=200):
if resp.status_code != expected_status_code:
fail("Unexpected HTTP status code", resp.status_code)
def check_content_type(resp, expected_content_type="application/json"):
ct = resp.header.get("Content-Type", [])
if len(ct) == 0 or not ct[0].startswith(expected_content_type):
fail("Unexpected Content-Type", ct)
# https://docs.gitlab.com/ee/api/issues.html#single-issue
def get_issue(w, issue_id):
resp = w.http.do(
url="%s/api/v4/issues/%d" % (w.vars.gitlab_url, issue_id),
header={
"Accept": "application/json",
"Authorization": AUTH_TOKEN,
},
)
check_status(resp)
check_content_type(resp)
return json.decode(str(resp.body))
# https://docs.gitlab.com/ee/api/issues.html#edit-issue
def edit_issue(w, project_id, issue_iid, labels=None, assignee_ids=None):
q = {}
if labels != None:
q["labels"] = ",".join(labels)
if assignee_ids != None:
q["assignee_ids"] = ",".join([
str(id)
for id in assignee_ids
])
resp = w.http.do(
method="PUT",
url="%s/api/v4/projects/%d/issues/%d" % (w.vars.gitlab_url, project_id, issue_iid),
header={
"Authorization": AUTH_TOKEN,
},
query=q,
)
check_status(resp)
# https://docs.gitlab.com/ee/api/notes.html#create-new-issue-note
def create_issue_note(w, project_id, issue_iid, body):
resp = w.http.do(
method="POST",
url="%s/api/v4/projects/%d/issues/%d/notes" % (w.vars.gitlab_url, project_id, issue_iid),
header={
"Authorization": AUTH_TOKEN,
},
query={
"body": body,
},
)
check_status(resp, 201)
# https://docs.gitlab.com/ee/api/issues.html#list-merge-requests-related-to-issue
def get_related_merge_requests(w, project_id, issue_iid):
resp = w.http.do(
url="%s/api/v4/projects/%d/issues/%d/related_merge_requests" % (w.vars.gitlab_url, project_id, issue_iid),
header={
"Accept": "application/json",
"Authorization": AUTH_TOKEN,
},
)
check_status(resp)
check_content_type(resp)
return json.decode(str(resp.body))
MILESTONE_BACKLOG_TITLE = "Backlog"
def is_milestone_set(issue):
milestone = issue.get("milestone")
return milestone != None and milestone["title"] != MILESTONE_BACKLOG_TITLE
def is_all_mrs_merged(mrs):
for mr in mrs:
if mr["state"] == "closed":
pass # ignore closed MRs
elif mr["state"] == "merged":
pass # found a merged MR, good!
else:
return False # in review, or something else
return True
def is_open_mrs_with_reviewer(mrs):
for mr in mrs:
if mr["state"] == "opened" and len(mr["reviewers"]) > 0:
return True
return False
def is_open_mrs(mrs):
for mr in mrs:
if mr["state"] == "opened":
return True
return False
def ensure_correct_issue_labels(w, ev):
issue = get_issue(w, ev["proto_data"]["issue"]["id"])
if issue["state"] == "closed":
print("Ignoring update to a closed issue")
return
labels = set(issue["labels"]) # mutable set. Remove all managed labels.
label_to_set = None
mrs = get_related_merge_requests(w, issue["project_id"], issue["iid"])
if is_open_mrs(mrs):
label_to_set = "workflow::in dev"
if is_milestone_set(issue):
label_to_set = "workflow::ready for development"
if label_to_set != None:
labels.add(label_to_set)
edit_issue(w, issue["project_id"], issue["iid"], labels=labels)
on_event(
type="com.gitlab.events.IssueUpdated",
handler=ensure_correct_issue_labels,
)
on_event(
type="com.gitlab.events.NewIssue",
handler=ensure_correct_issue_labels,
)