Skip to content

Commit

Permalink
Issue Templates and Automations (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfiex authored Apr 21, 2024
1 parent 8135652 commit b7ba76f
Show file tree
Hide file tree
Showing 11 changed files with 465 additions and 4 deletions.
35 changes: 35 additions & 0 deletions .github/ISSUE_TEMPLATE/add-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Add Activity
about: Adding a new activity
title: 'New Activity'
labels: 'add_activity'
assignees: ''

---

# Add Activity ID

To request a new item please ammend the following template below to reflect the items you are interested in.

Conditions on naming conventions and permissable items can be found on the [WIKI/activity_id](https://wiki.mipcvs.dev/CMIP6Plus/Rules/activity_id/)

<!--- info
We are trialing the addition of new components using the configuration file format.
To use this please fill out the template below keeping the spacing and indentation of the file.
--->

## Contents (what we wish to add)


``` configfile
[activity]
Name = "CMIP"
Long_Name = "Coupled Model Intercomparison Project"
URL = "https://wcrp-cmip.org"
```


17 changes: 17 additions & 0 deletions .github/ISSUE_TEMPLATE/default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: Other
about: Creating a general issue
title: 'Add a descriptive summary here.'
labels: ''
assignees: ''

---

# General Issue

Please provided a detailed outline of the problem, discussion or suggestion.

Make sure to provide the following where it might apply.

- [ ] Any relevant files or code snippets
- [ ] Where this occurs
96 changes: 96 additions & 0 deletions .github/libs/action_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

import os,sys,json,ast
import re,configparser
from io import StringIO


def parse_md(body):
# remove comments
pattern = r'<!---(.*?)--->'

# Remove comments using re.sub
body = re.sub(r'/r/n',r'/n', re.sub(pattern, '', body, flags=re.DOTALL))


config_str = re.search(r'```\sconfigfile(.*?)```',body, re.DOTALL).group(1)
print(config_str)

# Create a file-like object from the string
config_file = StringIO(config_str)

# Create a ConfigParser object
config = configparser.ConfigParser()

# Read configuration from the file-like object
config.read_file(config_file)

# Initialize an empty dictionary to hold the configuration data
config_dict = {}

# Iterate over sections and options
for section in config.sections():
config_dict[section] = {}
for option in config.options(section):
config_dict[section][option] = ast.literal_eval(config.get(section, option))

return config_dict


def dispatch(token,payload,repo):

import json
from urllib import request

# Construct the request headers
headers = {
"Accept": "application/vnd.github.everest-preview+json",
"Authorization": f"token {token}",
"Content-Type": "application/json"
}

# Encode the payload
datapayload = json.dumps(payload).encode('utf-8')

# Make the POST request
req = request.Request(f"{repo}/dispatches", data=datapayload, headers=headers, method='POST')

# Perform the request
try:
with request.urlopen(req) as response:
if response.getcode() == 204:
print("Dispatch event triggered successfully.")
else:
print(f"Failed to trigger dispatch event. Status code: {response.getcode()}")
print(response.read().decode('utf-8'))
except Exception as e:
print(f"Error: {e}")


def update_issue_title (issue_number,kind,payload):
# change issue name to reflect contents.
print(os.popen(f'gh issue edit {issue_number} --title "Add {kind}: {payload["client_payload"]["name"]}"').read())


def update_issue(issue_number,comment,err=True):
out = os.popen(f'gh issue comment {issue_number} --body "{comment}"')
if err:
print(out)
sys.exit(comment)

def close_issue(issue_number, comment,err=True):
print(os.popen(f'gh issue close {issue_number} -c "{comment}"'))
if err: sys.exit(comment)

def jr(file):
return json.load(open(file,'r'))

def jw(data,file):
return json.dump(data,open(file,'w'), indent=4)

def getfile(fileend):
import glob
return glob.glob(f'*{fileend}.json')

def pp(js):
import pprint
pprint.pprint(js)
44 changes: 44 additions & 0 deletions .github/libs/add/Activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

import json,sys,os,re

# Get the parent directory of the current file
parent_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir)

from action_functions import parse_md, dispatch, update_issue_title


issue_number = os.environ.get('ISSUE_NUMBER')
issue_title = os.environ.get('ISSUE_TITLE')
issue_body = os.environ.get('ISSUE_BODY')
issue_submitter = os.environ.get('ISSUE_SUBMITTER')
repo = os.environ.get('REPO').replace('https://github.com','https://api.github.com/repos')
token = os.environ.get('GH_TOKEN')


parsed = parse_md(issue_body)


'''
Lets submit the data to a dispatch event
'''


data = parsed['activity']

kind = __file__.split('/')[-1].replace('.py','')

payload = {
"event_type": kind,
"client_payload": {
"name": data['name'], # we need this to define the pull request
"issue": issue_number,
"author" : issue_submitter,
"data" : json.dumps(data)
}
}

update_issue_title(issue_number,kind,payload)

dispatch(token,payload,repo)

59 changes: 59 additions & 0 deletions .github/libs/parse/Activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import json, os, sys
from collections import OrderedDict

# Get the parent directory of the current file
parent_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir)

from action_functions import update_issue,jr,jw,getfile,close_issue,pp

# data
issue_number = os.environ['ISSUE']
data = os.environ['PAYLOAD_DATA']
data = json.loads(str(data))


# Load Existing
activities = jr(getfile('activity_id')[0])
alist = activities['activity_id']


import urllib.request

def url_exists(url):
try:
urllib.request.urlopen(url)
return True
except urllib.error.HTTPError:
return False
except urllib.error.URLError:
return False



if data['name'] in activities:
close_issue(issue_number,f'# Closing issue. \n {data["name"]} already exists in the activity list. \n\n Please review request and resubmit.')

if not url_exists(data['url']):
update_issue(issue_number,f"#Invalid URL \n {data['url']} does not appear to be valid")


# add
alist[data['name']] = OrderedDict({'URL': data['url'],'long_name': data['long_name']})
pp(dict(alist[data['name']]))
# sort and update
activities['activity_id'] = OrderedDict(sorted(alist.items()))



# Serialize back to JSON
new_json_data = jw(data, getfile('activity_id')[0])









125 changes: 125 additions & 0 deletions .github/workflows/dispatch_all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
name: New Dispatch Action (+ data)
on:
repository_dispatch:
types:
- Activity
- Experiment
- Source
- Component

jobs:
process-payload:
runs-on: ubuntu-latest
permissions:
actions: write
checks: write
contents: write
deployments: write
id-token: write
issues: write
# discussions: write
packages: write
pages: write
pull-requests: write
repository-projects: write
# security-events: write
statuses: write

steps:
- name: Checkout Repository
uses: actions/checkout@v2

- name: Print Payload
run: |
echo "kind of aciton: ${{ github.event.action }}"
echo "Received Payload from"
echo "author: ${{ github.event.client_payload.author }}"
echo "Received Payload:"
echo "${{ toJson(github.event.client_payload) }}"
- name: Create Pull Request
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REQ_AUTHOR: ${{ github.event.client_payload.author }}
PAYLOAD_DATA: ${{ github.event.client_payload.data }}
NAME: ${{ github.event.client_payload.name }}
ISSUE: ${{ github.event.client_payload.issue }}
KIND: ${{ github.event.action }}

run: |
base_branch="main"
feature_branch="consortium_$NAME"
git pull
remote_branch='origin/$feature_branch'
branch_info=$(git rev-parse --verify '$remote_branch' >/dev/null 2>&1 || true)
echo "branch info: $branch_info"
if [ -n "$branch_info" ]; then
echo "checkout existing"
git checkout $feature_branch
git reset --hard origin/main
else
echo "checkout new"
git checkout -b $feature_branch
fi
# debug uncomment
# python .github/libs/parse/${KIND}.py
content=$( python .github/libs/parse/${KIND}.py )
echo "${REQ_AUTHOR}"
git config --global user.email "${REQ_AUTHOR}@users.noreply.github.com"
git config --global user.name "${REQ_AUTHOR}"
git add -A
git commit -m "Adding $NAME to ${KiND}"
git push origin $feature_branch --force
if [ -n "$branch_info" ]; then
pull_requests=$(curl -s -H "Authorization: token $GH_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/pulls?state=open&head=$feature_branch" | jq -r '.[].number')
echo "pull requests ${pull_requests}"
for pr_number in $pull_requests; do
echo "running pull request $pr_number"
comment_body="This pull request (#$pr_number) was automatically updated by a GitHub Actions workflow.
Data submitted by @$REQ_AUTHOR
Adding the following updated data.
\`\`\`js
$content
\`\`\`
Resolves #$ISSUE
"
echo "comment- $comment_body"
gh pr comment $pr_number --body "$comment_body"
echo "Comment added to pull request #$pr_number"
done
else
echo "clean pull"
gh pr create --base $base_branch --head $feature_branch --title "New $KIND - add $NAME" --body \
"This pull request was automatically created by a GitHub Actions workflow.
Data submitted by @$REQ_AUTHOR
Adding the following new data.
\`\`\`js
$content
\`\`\`
Resolves #$ISSUE
" --reviewer $GITHUB_REPOSITORY_OWNER
fi
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit b7ba76f

Please sign in to comment.