Skip to content

Commit

Permalink
Script to re-enable GitHub Actions. (#121)
Browse files Browse the repository at this point in the history
Fixes #88.
  • Loading branch information
Michael Howitz committed Sep 8, 2021
1 parent af45ce3 commit faa88a9
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 26 deletions.
26 changes: 26 additions & 0 deletions config/README.rst
Expand Up @@ -625,3 +625,29 @@ The script does the following steps:

Running this script discards any uncommitted changes in the repositories it
runs on! There is no undo for this operation.


Re-enabling GitHub Actions
--------------------------

After a certain period of time (currently 60 days) without commits GitHub
automatically disables Actions. They can be re-enabled manually per repository.
There is a script to do this for all repositories. It does no harm if Actions
is already enabled for a repository.

Preparation
+++++++++++

* Install GitHub's CLI application, see https://github.com/cli/cli.

* Authorize using the application:

- ``gh auth login``
- It is probably enough to do it once.

Usage
+++++

To run the script just call it::

$ bin/python re-enable-actions.py
29 changes: 3 additions & 26 deletions config/multi-call.py
@@ -1,30 +1,12 @@
#!/usr/bin/env python3
from shared.call import call
from shared.packages import list_packages
from shared.path import change_dir
from shared.path import path_factory
import argparse
import pathlib
import sys


def path_factory(parameter_name, *, has_extension=None, is_dir=False):
"""Return factory creating pathlib.Path object if requirements are matched.
The factory raises an exception otherwise.
"""
def factory(str):
path = pathlib.Path(str)
if not path.exists():
raise argparse.ArgumentTypeError(f'{str!r} does not exist!')
if has_extension is not None and path.suffix != has_extension:
raise argparse.ArgumentTypeError(
f'The required extension is {has_extension!r}'
f' not {path.suffix!r}.')
if is_dir and not path.is_dir():
raise argparse.ArgumentTypeError('has to point to a directory!')
return path
return factory


parser = argparse.ArgumentParser(
description='Call a script on all repositories listed in a packages.txt.',
epilog='Additional optional arguments are passed directly to the script.')
Expand All @@ -42,12 +24,7 @@ def factory(str):

# idea from https://stackoverflow.com/a/37367814/8531312
args, sub_args = parser.parse_known_args()

packages = [
p
for p in args.packages_txt.read_text().split('\n')
if p and not p.startswith('#')
]
packages = list_packages(args.packages_txt)

for package in packages:
print(f'*** Running {args.script.name} on {package} ***')
Expand Down
55 changes: 55 additions & 0 deletions config/re-enable-actions.py
@@ -0,0 +1,55 @@
#!/bin/env python3
from shared.call import call
from shared.packages import list_packages
import argparse
import itertools
import pathlib


org = 'zopefoundation'
base_url = f'https://github.com/{org}'
base_path = pathlib.Path(__file__).parent
types = ['buildout-recipe', 'c-code', 'pure-python', 'zope-product']


parser = argparse.ArgumentParser(
description='Re-enable GitHub Actions for all repos in a packages.txt'
' files.')
parser.add_argument(
'--force-run',
help='Run workflow even it is already enabled.',
action='store_true')

args = parser.parse_args()
repos = itertools.chain(
*[list_packages(base_path / type / 'packages.txt')
for type in types])


def run_workflow(base_url, org, repo):
"""Manually start the tests.yml workflow of a repository."""
result = call('gh', 'workflow', 'run', 'tests.yml', '-R', f'{org}/{repo}')
if result.returncode != 0:
print('To enable manually starting workflows clone the repository'
' and run meta/config/config-package.py on it.')
print('Command to clone:')
print(f'git clone {base_url}/{repo}.git')
return False
return True


for repo in repos:
print(repo)
wfs = call(
'gh', 'workflow', 'list', '--all', '-R', f'{org}/{repo}',
capture_output=True).stdout
test_line = [x for x in wfs.splitlines() if x.startswith('test')][0]
if 'disabled_inactivity' not in test_line:
print(' ☑️ already enabled')
if args.force_run:
run_workflow(base_url, org, repo)
continue
test_id = test_line.split()[-1]
call('gh', 'workflow', 'enable', test_id, '-R', f'{org}/{repo}')
if run_workflow(base_url, org, repo):
print(' ✅ enabled')
13 changes: 13 additions & 0 deletions config/shared/packages.py
@@ -0,0 +1,13 @@
import pathlib


def list_packages(path: pathlib.Path) -> list:
"""List the packages in ``path``.
``path`` must point to a packages.txt file.
"""
return [
p
for p in path.read_text().split('\n')
if p and not p.startswith('#')
]
21 changes: 21 additions & 0 deletions config/shared/path.py
@@ -1,5 +1,7 @@
import argparse
import contextlib
import os
import pathlib


@contextlib.contextmanager
Expand All @@ -14,3 +16,22 @@ def change_dir(path):
yield cwd
finally:
os.chdir(cwd)


def path_factory(parameter_name, *, has_extension=None, is_dir=False):
"""Return factory creating pathlib.Path object if requirements are matched.
The factory raises an exception otherwise.
"""
def factory(str):
path = pathlib.Path(str)
if not path.exists():
raise argparse.ArgumentTypeError(f'{str!r} does not exist!')
if has_extension is not None and path.suffix != has_extension:
raise argparse.ArgumentTypeError(
f'The required extension is {has_extension!r}'
f' not {path.suffix!r}.')
if is_dir and not path.is_dir():
raise argparse.ArgumentTypeError('has to point to a directory!')
return path
return factory

0 comments on commit faa88a9

Please sign in to comment.