Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .github/ISSUE_TEMPLATE/delete.md

This file was deleted.

18 changes: 0 additions & 18 deletions .github/ISSUE_TEMPLATE/register.md

This file was deleted.

11 changes: 0 additions & 11 deletions .github/ISSUE_TEMPLATE/update.md

This file was deleted.

149 changes: 56 additions & 93 deletions .github/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,14 @@

INDEX_FILE = "index.html"
TEMPLATE_FILE = "pkg_template.html"
YAML_ACTION_FILES = [".github/workflows/delete.yml", ".github/workflows/update.yml"]


def normalize(name):
""" From PEP503 : https://www.python.org/dev/peps/pep-0503/ """
return re.sub(r"[-_.]+", "-", name).lower()


def parse_issue(issue_ctx):
arguments = {}

parts = issue_ctx['body'].split('- **')[1:] # Ignore the first one : it's the title
for text_arg in parts:
arg_name, arg_value = text_arg.split(':**')
arg_name, arg_value = arg_name.strip(), arg_value.strip()

if arg_name == "Long description":
# Special case, where we have more than 1 line : it contain HTML code
arg_value = arg_value.split('```')[1] if '```' in arg_value else arg_value.split('`')[1]

code_lang = arg_value.split('\n')[0].strip()
if code_lang != 'html':
raise ValueError("The {} argument should contain a HTML code section. But it contain {} code.".format(arg_name, code_lang))

arg_value = "\n".join(arg_value.split('\n')[1:])
else:
if "\n" in arg_value:
raise ValueError("The {} argument should be a single line. Current value : {}".format(arg_name, arg_value))

arguments[arg_name.lower()] = arg_value
return arguments


def print_args(args):
print("\n--- Arguments detected from issue ---\n")
for arg_name, arg_value in args.items():
print("\t{} : {}".format(arg_name, arg_value))
print("\n")


def check_args(args, must_have):
for name in must_have:
if name not in args:
raise ValueError("Couldn't find argument {}".format(name))
if args[name].strip() == "":
raise ValueError("Argument {} is empty. Please specify it".format(name))


def package_exists(soup, package_name):
package_ref = package_name + "/"
for anchor in soup.find_all('a'):
Expand All @@ -64,25 +25,23 @@ def package_exists(soup, package_name):
return False


def register(issue_ctx):
args = parse_issue(issue_ctx)
print_args(args)
check_args(args, ['package name', 'version', 'author', 'short description', 'long description', 'homepage', 'link'])
def register(pkg_name, version, author, short_desc, long_desc, homepage, link):
# Read our index first
with open(INDEX_FILE) as html_file:
soup = BeautifulSoup(html_file, "html.parser")
n_package_name = normalize(args['package name'])
norm_pkg_name = normalize(pkg_name)

if package_exists(soup, n_package_name):
raise ValueError("Package {} seems to already exists".format(n_package_name))
if package_exists(soup, norm_pkg_name):
raise ValueError("Package {} seems to already exists".format(norm_pkg_name))

# Create a new anchor element for our new package
last_anchor = soup.find_all('a')[-1] # Copy the last anchor element
new_anchor = copy.copy(last_anchor)
new_anchor['href'] = "{}/".format(n_package_name)
new_anchor.contents[0].replace_with(args['package name'])
new_anchor['href'] = "{}/".format(norm_pkg_name)
new_anchor.contents[0].replace_with(pkg_name)
spans = new_anchor.find_all('span')
spans[1].string = args['version'] # First span contain the version
spans[2].string = args['short description'] # Second span contain the short description
spans[1].string = version # First span contain the version
spans[2].string = short_desc # Second span contain the short description

# Add it to our index and save it
last_anchor.insert_after(new_anchor)
Expand All @@ -93,93 +52,97 @@ def register(issue_ctx):
with open(TEMPLATE_FILE) as temp_file:
template = temp_file.read()

template = template.replace("_package_name", args['package name'])
template = template.replace("_version", args['version'])
template = template.replace("_link", "{}#egg={}-{}".format(args['link'], n_package_name, args['version']))
template = template.replace("_homepage", args['homepage'])
template = template.replace("_author", args['author'])
template = template.replace("_long_description", args['long description'])
template = template.replace("_package_name", pkg_name)
template = template.replace("_version", version)
template = template.replace("_link", "{}#egg={}-{}".format(link, norm_pkg_name, version))
template = template.replace("_homepage", homepage)
template = template.replace("_author", author)
template = template.replace("_long_description", long_desc)

os.mkdir(n_package_name)
package_index = os.path.join(n_package_name, INDEX_FILE)
os.mkdir(norm_pkg_name)
package_index = os.path.join(norm_pkg_name, INDEX_FILE)
with open(package_index, "w") as f:
f.write(template)


def update(issue_ctx):
args = parse_issue(issue_ctx)
print_args(args)
check_args(args, ['package name', 'new version', 'link for the new version'])
def update(pkg_name, version, link):
# Read our index first
with open(INDEX_FILE) as html_file:
soup = BeautifulSoup(html_file, "html.parser")
n_package_name = normalize(args['package name'])
norm_pkg_name = normalize(pkg_name)

if not package_exists(soup, n_package_name):
raise ValueError("Package {} seems to not exists".format(n_package_name))
if not package_exists(soup, norm_pkg_name):
raise ValueError("Package {} seems to not exists".format(norm_pkg_name))

# Change the version in the main page
anchor = soup.find('a', attrs={"href": "{}/".format(n_package_name)})
anchor = soup.find('a', attrs={"href": "{}/".format(norm_pkg_name)})
spans = anchor.find_all('span')
spans[1].string = args['new version']
spans[1].string = version
with open(INDEX_FILE, 'wb') as index:
index.write(soup.prettify("utf-8"))

# Change the package page
index_file = os.path.join(n_package_name, INDEX_FILE)
index_file = os.path.join(norm_pkg_name, INDEX_FILE)
with open(index_file) as html_file:
soup = BeautifulSoup(html_file, "html.parser")

# Create a new anchor element for our new version
last_anchor = soup.find_all('a')[-1] # Copy the last anchor element
new_anchor = copy.copy(last_anchor)
new_anchor['href'] = "{}#egg={}-{}".format(args['link for the new version'], n_package_name, args['new version'])
new_anchor['href'] = "{}#egg={}-{}".format(link, norm_pkg_name, version)

# Add it to our index
last_anchor.insert_after(new_anchor)

# Change the latest version
soup.html.body.div.section.find_all('span')[1].contents[0].replace_with(args['new version'])
soup.html.body.div.section.find_all('span')[1].contents[0].replace_with(version)

# Save it
with open(index_file, 'wb') as index:
index.write(soup.prettify("utf-8"))


def delete(issue_ctx):
args = parse_issue(issue_ctx)
print_args(args)
check_args(args, ['package name'])
def delete(pkg_name):
# Read our index first
with open(INDEX_FILE) as html_file:
soup = BeautifulSoup(html_file, "html.parser")
n_package_name = normalize(args['package name'])
norm_pkg_name = normalize(pkg_name)

if not package_exists(soup, n_package_name):
raise ValueError("Package {} seems to not exists".format(n_package_name))
if not package_exists(soup, norm_pkg_name):
raise ValueError("Package {} seems to not exists".format(norm_pkg_name))

# Remove the package directory
shutil.rmtree(n_package_name)
shutil.rmtree(norm_pkg_name)

# Find and remove the anchor corresponding to our package
anchor = soup.find('a', attrs={"href": "{}/".format(n_package_name)})
anchor = soup.find('a', attrs={"href": "{}/".format(norm_pkg_name)})
anchor.extract()
with open(INDEX_FILE, 'wb') as index:
index.write(soup.prettify("utf-8"))


def main():
# Get the context from the environment variable
context = json.loads(os.environ['GITHUB_CONTEXT'])
issue_ctx = context['event']['issue']
title = issue_ctx['title']

if title.startswith("🟢"):
register(issue_ctx)

if title.startswith("🔵"):
update(issue_ctx)

if title.startswith("🔴"):
delete(issue_ctx)
# Call the right method, with the right arguments
action = os.environ["PKG_ACTION"]

if action == "REGISTER":
register(
pkg_name=os.environ["PKG_NAME"],
version=os.environ["PKG_VERSION"],
author=os.environ["PKG_AUTHOR"],
short_desc=os.environ["PKG_SHORT_DESC"],
long_desc=os.environ["PKG_LONG_DESC"],
homepage=os.environ["PKG_HOMEPAGE"],
link=os.environ["PKG_LINK"],
)
elif action == "DELETE":
delete(pkg_name=os.environ["PKG_NAME"])
elif action == "UPDATE":
update(
pkg_name=os.environ["PKG_NAME"],
version=os.environ["PKG_VERSION"],
link=os.environ["PKG_LINK"],
)


if __name__ == "__main__":
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/delete.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: delete

on:
workflow_dispatch:
inputs:
package_name:
description: Package name
required: true
type: string

jobs:
delete:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Run Action
env:
PKG_ACTION: DELETE
PKG_NAME: ${{ inputs.package_name }}
run: |
pip install beautifulsoup4
python .github/actions.py
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
commit-message: ':package: [:robot:] Delete package from PyPi index'
title: '[🤖] Delete `${{ inputs.package_name }}` from PyPi index'
body: Automatically generated PR, deleting `${{ inputs.package_name }}` from
PyPi index.
branch-suffix: random
delete-branch: true
69 changes: 69 additions & 0 deletions .github/workflows/register.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: register

on:
workflow_dispatch:
inputs:
package_name:
description: 'Package name'
required: true
type: string
version:
description: 'Version of the package'
required: true
type: string
author:
description: 'Author(s) of the package'
required: true
type: string
short_desc:
description: 'A short description of the package'
required: true
type: string
long_desc:
description: 'A longer description of the package (HTML)'
required: true
type: string
homepage:
description: 'Homepage of the package (link to the github repository)'
required: true
type: string
link:
description: 'Link used for `pip`. For example, for a github-hosted package refered by the tag `v3.0.2`, it would be : git+https://github.com/huggingface/transformers@v3.0.2'
required: true
type: string

jobs:
update:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Run Action
env:
PKG_ACTION: REGISTER
PKG_NAME: ${{ inputs.package_name }}
PKG_VERSION: ${{ inputs.version }}
PKG_AUTHOR: ${{ inputs.author }}
PKG_SHORT_DESC: ${{ inputs.short_desc }}
PKG_LONG_DESC: ${{ inputs.long_desc }}
PKG_HOMEPAGE: ${{ inputs.homepage }}
PKG_LINK: ${{ inputs.link }}
run: |
pip install beautifulsoup4
python .github/actions.py
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
commit-message: ':package: [:robot:] Register package in PyPi index'
title: '[🤖] Register `${{ inputs.package_name }}` in PyPi index'
body: Automatically generated PR, registering `${{ inputs.package_name }}` in PyPi
index.
branch-suffix: random
delete-branch: true
Loading