Add more triggers for autoflow
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,
)