From a8bfa547e7a659c7bc00a4c0ee4ad2372b37526d Mon Sep 17 00:00:00 2001 From: Sebastian Bauersfeld Date: Fri, 29 Jul 2022 10:35:38 +0700 Subject: [PATCH] update --- .github/workflows/record-codeql-versions.yml | 6 +-- cli.py | 50 +++++++++++++++++--- record-codeql-version => cliver.py | 42 ++++++++-------- 3 files changed, 68 insertions(+), 30 deletions(-) rename record-codeql-version => cliver.py (73%) diff --git a/.github/workflows/record-codeql-versions.yml b/.github/workflows/record-codeql-versions.yml index cdd7602..42d90da 100644 --- a/.github/workflows/record-codeql-versions.yml +++ b/.github/workflows/record-codeql-versions.yml @@ -2,8 +2,8 @@ name: "Record CodeQL Versions" on: workflow_dispatch: -# push: -# branches: [main] + push: + branches: [main] schedule: - cron: '0 */6 * * *' @@ -31,4 +31,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | version="$("${{ steps.downloadcli.outputs.codeql-path }}" version -q)" - ./record-codeql-version "$version" + ./cliver.py "${{ github.repository }}" "codeql-versions-on-actions" "$version" diff --git a/cli.py b/cli.py index 241386b..6d625b4 100644 --- a/cli.py +++ b/cli.py @@ -12,6 +12,7 @@ import tarfile import atexit from subprocess import CalledProcessError +import cliver def get_codeql(args, location): @@ -196,6 +197,18 @@ def make_min_db(args): ) +def actions_cli_version(args): + print( + cliver.get_latest_version( + args.repository, + cliver.ensure_release( + args.repository, + args.release, + ) + ) + ) + + def mustbefile(path): if not isfile(path): error(f'"{path}" is not a file!') @@ -220,24 +233,30 @@ def mustnotexist(path): return path +def mustbepackname(string): + if not string or len(string.split('/')) != 2: + error(f'"{string}" is not a valid package name! It must be of the form "scope/name".') + return string + + def mustbepack(path): if not util.is_pack(path): error(f'Path "{path}" is not a (Code)QL pack!') return path +def mustberepoid(string): + if not string or len(string.split('/')) != 2: + error(f'"{string}" is not a valid repository id! It must be of the form "owner/name".') + return string + + def mustbedist(path): if not util.is_dist(path): error(f'Path "{path}" is not a CodeQL distribution!') return path -def mustbepackname(string): - if not string or len(string.split('/')) != 2: - error(f'"{string}" is not a valid package name! It must be of the form "scope/name".') - return string - - def main(): global tempdir tempdir = tempfile.mkdtemp() @@ -537,6 +556,25 @@ def main(): ) sp.set_defaults(func=make_min_db) + sp = subparsers.add_parser( + 'actions-cli-version', + help='Retrieve the version of the CodeQL CLI currenty installed on GitHub Actions', + description='Retrieve the version of the CodeQL CLI currenty installed on GitHub Actions', + ) + sp.add_argument( + '-r', '--repository', + required=False, + type=mustberepoid, + default='zbazztian/gh-tailor', + help='The repository ("owner/name") from which to fetch the information.', + ) + sp.add_argument( + '-s', '--release', + default='codeql-versions-on-actions', + help='The name of the release from which to fetch the information.', + ) + sp.set_defaults(func=actions_cli_version) + def print_usage(args): print(parser.format_usage()) diff --git a/record-codeql-version b/cliver.py similarity index 73% rename from record-codeql-version rename to cliver.py index e4a3751..40f148f 100755 --- a/record-codeql-version +++ b/cliver.py @@ -18,8 +18,6 @@ RESULTS_PER_PAGE = 100 API_URL = 'https://api.github.com' -REPO_ID = 'zbazztian/gh-tailor' -RELEASE_ID = 'codeql-versions-for-actions' def parse_link_header(value): @@ -75,11 +73,11 @@ def info(msg): def now(): - return datetime.strftime(datetime.now(), '%Y-%m-%dT%H:%M:%SZ') + return datetime.strftime(datetime.now(), '%Y-%m-%dT%H:%M:%S%z') def parse_date(datestr): - return datetime.strptime(datestr, '%Y-%m-%dT%H:%M:%SZ') + return datetime.strptime(datestr, '%Y-%m-%dT%H:%M:%S%z') def sort_by_created_at(releasesorassets): @@ -91,9 +89,10 @@ def sort_by_created_at(releasesorassets): def default_headers(): + token = os.environ.get('GITHUB_TOKEN', None) return { - 'Authorization': f'token {os.environ["GITHUB_TOKEN"]}', 'Accept': 'application/vnd.github.v3+json', + **({'Authorization': f'token {token}'} if token else {}) } @@ -104,17 +103,17 @@ def latest_asset(release: str, assetfilter: str): return None -def latest_version(release): +def get_latest_version(repo_id: str, release: str): a = latest_asset( release, 'version-*' ) - return read_asset(a) if a else None + return read_asset(repo_id, a) if a else None -def read_asset(asset: str) -> str: +def read_asset(repo_id: str, asset: str) -> str: return request( - f'{API_URL}/repos/{REPO_ID}/releases/assets/{asset["id"]}', + f'{API_URL}/repos/{repo_id}/releases/assets/{asset["id"]}', headers={ **default_headers(), 'Accept': 'application/octet-stream', @@ -123,8 +122,8 @@ def read_asset(asset: str) -> str: )[2] -def list_releases(): - url = f'{API_URL}/repos/{REPO_ID}/releases?per_page={RESULTS_PER_PAGE}' +def list_releases(repo_id: str): + url = f'{API_URL}/repos/{repo_id}/releases?per_page={RESULTS_PER_PAGE}' while True: _, headers, body = request( @@ -141,21 +140,21 @@ def list_releases(): break -def get_release(releasefilter): - for r in sort_by_created_at(list_releases()): +def get_release(repo_id: str, releasefilter: str): + for r in sort_by_created_at(list_releases(repo_id)): if fnmatch(r['tag_name'], releasefilter): return r return None -def ensure_release(rid: str) -> str: - return get_release(rid) or create_release(rid, 'main') +def ensure_release(repo_id: str, release_id: str) -> str: + return get_release(repo_id, release_id) or create_release(repo_id, release_id, 'main') -def create_release(tag, revision): +def create_release(repo_id: str, tag: str, revision: str): return json.loads( request( - f'{API_URL}/repos/{REPO_ID}/releases', + f'{API_URL}/repos/{repo_id}/releases', data=json.dumps({ 'tag_name': tag, 'target_commitish': revision, @@ -180,18 +179,19 @@ def upload_asset(release, assetname, data): ) -def upload_latest_version(version: str) -> None: - r = ensure_release(RELEASE_ID) +def set_latest_version(repo_id: str, release_id: str, version: str) -> None: + r = ensure_release(repo_id, release_id) assetname = f'version-{now()}' for a in r['assets']: if assetname == a['name']: info(f'"{assetname}" was previously uploaded. Nothing left to do.') return - if latest_version(r) == version: + if get_latest_version(repo_id, r) == version: info(f'Latest version did not change ({version}). Nothing left to do.') return info(f'Setting newest version to "{version}".') upload_asset(r, assetname, version.encode('utf-8')) -upload_latest_version(sys.argv[1]) +if __name__ == '__main__': + set_latest_version(sys.argv[1], sys.argv[2], sys.argv[3])