Skip to content

Commit

Permalink
chore: enable Github trigger listener
Browse files Browse the repository at this point in the history
  • Loading branch information
RRanath committed Sep 5, 2024
1 parent 3933e2a commit b1aacbb
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/deploy_tools_chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ jobs:
openshift_token: ${{ secrets.OPENSHIFT_TOKEN }}
insecure_skip_tls_verify: true
- run: |
helm upgrade ccbc-tools helm/ccbc-tools --install --atomic -n ${{ secrets.NAMESPACE_PREFIX }}-tools --set namespacePrefix=${{ secrets.NAMESPACE_PREFIX }}
helm upgrade ccbc-tools helm/ccbc-tools --install --atomic -n ${{ secrets.NAMESPACE_PREFIX }}-tools --set namespacePrefix=${{ secrets.NAMESPACE_PREFIX }} --set deployer.githubToken=${{ secrets.TEKTON_GITHUB}} --set deployer.headerSecret=${{ secrets.JIRA_SECRET }}
23 changes: 23 additions & 0 deletions helm/ccbc-tools/templates/ci-cd/eventlistener.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
name: jira-sprint-done-event-listener
spec:
triggers:
- bindings:
- kind: TriggerBinding
name: key
value: $(body.issue.key)
- kind: TriggerBinding
name: signature
value: '$(header[''Ccbc-Jira-Header''])'
interceptors:
- params:
- name: filter
value: 'header[''Ccbc-Jira-Header''] != null'
ref:
kind: ClusterInterceptor
name: cel
name: trigger-github
template:
ref: trigger-github-merge-and-release
16 changes: 16 additions & 0 deletions helm/ccbc-tools/templates/ci-cd/route.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
kind: Route
apiVersion: route.openshift.io/v1
metadata:
name: ccbc-jira-sprint-done-el
spec:
host: ccbc-jira-sprint-done-el.apps.silver.devops.gov.bc.ca
to:
kind: Service
name: el-jira-sprint-done-event-listener
weight: 100
port:
targetPort: http-listener
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
wildcardPolicy: None
8 changes: 8 additions & 0 deletions helm/ccbc-tools/templates/ci-cd/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
kind: Secret
apiVersion: v1
metadata:
name: trigger-deploy-secret
data:
headerSecret: {{ .Values.deployer.headerSecret | b64enc | quote }}
githubToken: {{ .Values.deployer.githubToken | b64enc | quote }}
type: Opaque
44 changes: 44 additions & 0 deletions helm/ccbc-tools/templates/ci-cd/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: trigger-github-merge-and-release
spec:
params:
- default: bcgov
description: Repo owner argument
name: arg1
type: string
- default: CONN-CCBC-portal
description: Repo name argument
name: arg2
type: string
- description: Branch name prefix (JIRA Key)
name: arg3
type: string
- description: Received header signature key passed from EL
name: arg4
type: string
steps:
- args:
- /workspace/source/lib/ci_cd/merge_process.py
- $(params.arg1)
- $(params.arg2)
- $(params.arg3)
- $(params.arg4)
command:
- python
env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
key: githubToken
name: trigger-deploy-secret
- name: HEADER_SECRET
valueFrom:
secretKeyRef:
key: headerSecret
name: trigger-deploy-secret
image: >-
image-registry.openshift-image-registry.svc:5000/ff61fb-tools/python-3-11-with-requests
name: run-python
resources: {}
23 changes: 23 additions & 0 deletions helm/ccbc-tools/templates/ci-cd/triggertemplate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
name: trigger-github-merge-and-release
spec:
params:
- description: The issue key
name: key
- description: The header key
name: signature
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: run-trigger-github-merge-and-release-
spec:
params:
- name: arg3
value: $(tt.params.key)
- name: arg4
value: $(tt.params.signature)
taskRef:
name: trigger-github-merge-and-release
53 changes: 53 additions & 0 deletions helm/ccbc-tools/templates/deployer/deployerRole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,58 @@ rules:
- update
- patch
- delete
- apiGroups:
- build.openshift.io
resources:
- buildconfigs
verbs:
- get
- list
- create
- update
- delete
- patch
- apiGroups:
- image.openshift.io
resources:
- imagestreams
verbs:
- get
- list
- create
- update
- delete
- patch
- apiGroups:
- tekton.dev
resources:
- tasks
- taskruns
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- triggers.tekton.dev
resources:
- eventlisteners
- interceptors
- triggers
- triggerbindings
- triggertemplates
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch

{{ end }}
2 changes: 2 additions & 0 deletions helm/ccbc-tools/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ namespacePrefix: ~
deployer:
serviceAccount:
enabled: true
githubToken: '' # The GitHub token must be passed in via the deploy script
headerSecret: '' # The header secret must be passed in via the deploy script

linter:
serviceAccount:
Expand Down
150 changes: 150 additions & 0 deletions lib/ci_cd/merge_process.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import sys
import json
import os
import requests

def find_pr_by_partial_branch(repo_owner, repo_name, branch_name):
# Make a GET request to the GitHub API with a partial branch name
response = requests.get(f"https://api.github.com/search/issues?q=repo:{repo_owner}/{repo_name}+head:{branch_name}+is:pr")

# Check if the request was successful
if response.status_code != 200:
print("Failed to retrieve PRs: Repository or branch not found.")
sys.exit(1)

try:
# Convert response text to JSON
data = response.json()
except json.JSONDecodeError as e:
print(f"Failed to decode JSON response: {e}")
sys.exit(1)

# Filter out control characters from the JSON response
cleaned_response = {k: v.translate({0: None, 127: None}) if isinstance(v, str) else v for k, v in data.items()}

# Extract the URL of the first pull request (if any)
try:
pr_api_url = cleaned_response["items"][0]["url"]
except (KeyError, IndexError):
print("No PR found for the specified branch.")
sys.exit(1)

if pr_api_url:
return pr_api_url
else:
print("No PR found for the specified branch.")

def update_pr_description(pr_url, token):
# Get the PR details
headers = {"Accept": "application/vnd.github.v3+json", "Authorization": f"token {token}"}
response = requests.get(pr_url, headers=headers)

if response.status_code != 200:
print(f"Failed to retrieve PR details: {response.status_code}")
return

pr_details = response.json()

# Check if the PR body already contains the checkbox
checked_checkbox = "- [x] Check me to trigger auto merge process."
if checked_checkbox in pr_details["body"]:
print("Checkbox already exists in the PR description.")
else:
# Update the PR description
existing_checkbox = "- [ ] Check me to trigger auto merge process."
new_description = pr_details["body"].replace(existing_checkbox, "- [ ] Check me to trigger auto merge process. edited by script")
pr_details["body"] = new_description

# Send the updated PR details
response = requests.patch(pr_url, headers=headers, json={"body": new_description})

if response.status_code == 200:
print("PR description updated successfully!")
else:
print(f"Failed to update PR description: {response.status_code}")

def get_pull_request_id(pr_url, token):
# Extract pull request number from the URL
pr_number = pr_url.split("/")[-1]

# GraphQL query to get pull request ID
query = """
query GetPullRequestID {
repository(owner: "%s", name: "%s") {
pullRequest(number: %s) {
id
}
}
}
""" % (repo_owner, repo_name, pr_number)

# Send GraphQL request
headers = {"Authorization": f"Bearer {token}"}
response = requests.post("https://api.github.com/graphql", json={"query": query}, headers=headers)

if response.status_code != 200:
print(f"Failed to retrieve pull request ID: {response.status_code}")
return None

data = response.json()
pull_request_id = data.get("data", {}).get("repository", {}).get("pullRequest", {}).get("id")
return pull_request_id

def enable_auto_merge(pull_request_id, token):
# GraphQL mutation to enable auto merge
mutation = """
mutation EnableAutoMerge {
enablePullRequestAutoMerge(input: {pullRequestId: "%s", mergeMethod: MERGE}) {
clientMutationId
}
}
""" % pull_request_id

# Send GraphQL request
headers = {"Authorization": f"Bearer {token}"}
# response = requests.post("https://api.github.com/graphql", json={"query": mutation}, headers=headers)

# if response.status_code != 200:
# print(f"Failed to enable auto merge: {response.status_code}")
# return

print("Auto merge enabled successfully!")

def check_header_secret(passed_value):
# Get the value of the environment variable named HEADER_SECRET
header_secret = os.environ.get('HEADER_SECRET')

# Check if passed_value is equal to expected header_secret
if passed_value == header_secret:
return True
else:
return False

if __name__ == "__main__":
if len(sys.argv) != 5:
print("Usage: python script.py <repo_owner> <repo_name> <branch_name> <passed_header>")
sys.exit(1)

repo_owner = sys.argv[1]
repo_name = sys.argv[2]
branch_name = sys.argv[3]
passed_header = sys.argv[4]
token = os.environ.get('GITHUB_TOKEN')

if not check_header_secret(passed_header):
print("Invalid header secret.")
sys.exit(1)

print(repo_owner, repo_name, branch_name, passed_header, token)

pr_url = find_pr_by_partial_branch(repo_owner, repo_name, branch_name)

update_pr_description(pr_url, token)

parts = pr_url.split("/")
repo_owner = parts[4]
repo_name = parts[5]

pull_request_id = get_pull_request_id(pr_url, token)
if pull_request_id:
enable_auto_merge(pull_request_id, token)

0 comments on commit b1aacbb

Please sign in to comment.