104 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
"""Download packages from github actions artifacts
 | 
						|
"""
 | 
						|
 | 
						|
import os
 | 
						|
import re
 | 
						|
import sys
 | 
						|
import logging
 | 
						|
import datetime as dt
 | 
						|
from pathlib import Path
 | 
						|
 | 
						|
import requests
 | 
						|
 | 
						|
logger = logging.getLogger()
 | 
						|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
 | 
						|
 | 
						|
API_URL = "https://ci.appveyor.com/api"
 | 
						|
REPOS = "psycopg/psycopg2"
 | 
						|
WORKFLOW_NAME = "Build packages"
 | 
						|
 | 
						|
 | 
						|
class ScriptError(Exception):
 | 
						|
    """Controlled exception raised by the script."""
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    try:
 | 
						|
        token = os.environ["APPVEYOR_TOKEN"]
 | 
						|
    except KeyError:
 | 
						|
        raise ScriptError("please set a APPVEYOR_TOKEN to download artifacts")
 | 
						|
 | 
						|
    s = requests.Session()
 | 
						|
    s.headers["Content-Type"] = "application/json"
 | 
						|
    s.headers["Authorization"] = f"Bearer {token}"
 | 
						|
 | 
						|
    logger.info("fetching last run")
 | 
						|
    resp = s.get(f"{API_URL}/projects/{REPOS}/")
 | 
						|
    resp.raise_for_status()
 | 
						|
    data = resp.json()
 | 
						|
 | 
						|
    updated_at = dt.datetime.fromisoformat(
 | 
						|
        re.sub(r"\.\d+", "", data["build"]["finished"])
 | 
						|
    )
 | 
						|
    now = dt.datetime.now(dt.timezone.utc)
 | 
						|
    age = now - updated_at
 | 
						|
    logger.info(
 | 
						|
        f"found build {data['build']['version']} updated {pretty_interval(age)} ago"
 | 
						|
    )
 | 
						|
    if age > dt.timedelta(hours=6):
 | 
						|
        logger.warning("maybe it's a bit old?")
 | 
						|
 | 
						|
    jobs = data["build"]["jobs"]
 | 
						|
    for job in jobs:
 | 
						|
        if job["status"] != "success":
 | 
						|
            raise ScriptError("status for job {job['jobId']} is {job['status']}")
 | 
						|
 | 
						|
        logger.info(f"fetching artifacts info for {job['name']}")
 | 
						|
        resp = s.get(f"{API_URL}/buildjobs/{job['jobId']}/artifacts/")
 | 
						|
        resp.raise_for_status()
 | 
						|
        afs = resp.json()
 | 
						|
        for af in afs:
 | 
						|
            fn = af["fileName"]
 | 
						|
            if fn.startswith("dist/"):
 | 
						|
                fn = fn.split("/", 1)[1]
 | 
						|
            dest = Path("packages") / fn
 | 
						|
            logger.info(f"downloading {dest}")
 | 
						|
            resp = s.get(
 | 
						|
                f"{API_URL}/buildjobs/{job['jobId']}/artifacts/{af['fileName']}"
 | 
						|
            )
 | 
						|
            resp.raise_for_status()
 | 
						|
            if not dest.parent.exists():
 | 
						|
                dest.parent.mkdir()
 | 
						|
 | 
						|
            with dest.open("wb") as f:
 | 
						|
                f.write(resp.content)
 | 
						|
 | 
						|
    logger.info("now you can run: 'twine upload -s packages/*'")
 | 
						|
 | 
						|
 | 
						|
def pretty_interval(td):
 | 
						|
    secs = td.total_seconds()
 | 
						|
    mins, secs = divmod(secs, 60)
 | 
						|
    hours, mins = divmod(mins, 60)
 | 
						|
    days, hours = divmod(hours, 24)
 | 
						|
    if days:
 | 
						|
        return f"{int(days)} days, {int(hours)} hours, {int(mins)} minutes"
 | 
						|
    elif hours:
 | 
						|
        return f"{int(hours)} hours, {int(mins)} minutes"
 | 
						|
    else:
 | 
						|
        return f"{int(mins)} minutes"
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    try:
 | 
						|
        sys.exit(main())
 | 
						|
 | 
						|
    except ScriptError as e:
 | 
						|
        logger.error("%s", e)
 | 
						|
        sys.exit(1)
 | 
						|
 | 
						|
    except KeyboardInterrupt:
 | 
						|
        logger.info("user interrupt")
 | 
						|
        sys.exit(1)
 |