summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-03-28 21:48:43 +0200
committerJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-03-28 21:48:43 +0200
commitc71e64d211243e121b89fe19495576fbf58892cb (patch)
tree98c0f72bc9b4aa362c825bf506405e440c801dfe
parent23b621cec968f2feede3bce6df9fa5786e77002a (diff)
GitHub Actions: Add some comments regarding manifest generation
-rw-r--r--.github/workflows/build.yml8
-rw-r--r--tools/generate_download_metadata.py28
2 files changed, 33 insertions, 3 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 38bd7ee6e1..a7e5cb2338 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -333,8 +333,10 @@ jobs:
Add-Content -Path "$Env:GITHUB_ENV" -Value "PATH=$Env:PATH"
- name: "Generate Artifact Metadata"
- id: generate_artifact_metadata
- # skip deploying Ubuntu builds to downloads.mixxx.org because these are deployed to the PPA
+ # Generate metadata for file artifact and write it to the job output
+ # using the artifacts_slug value. This also sets the DEPLOY_DIR
+ # environment variable that is used in the deploy.sh script in the next
+ # step.
if: github.event_name == 'push'
run: python3 tools/generate_download_metadata.py artifact ${{ matrix.artifacts_path }} "${{ matrix.artifacts_slug }}"
env:
@@ -378,6 +380,8 @@ jobs:
fetch-depth: 0
- name: "Collect Artifacts Metadata & Write Manifest"
+ # Retrieve the metadata from the matrix job's outputs, merge them into a
+ # single JSON document and then deploy to the server.
if: github.event_name == 'push' && env.SSH_PASSWORD != null
run: python3 tools/generate_download_metadata.py manifest
env:
diff --git a/tools/generate_download_metadata.py b/tools/generate_download_metadata.py
index beea581c62..f3dbc954bf 100644
--- a/tools/generate_download_metadata.py
+++ b/tools/generate_download_metadata.py
@@ -13,7 +13,10 @@ import urllib.request
def url_fetch(url, headers=None, **kwargs):
+ """Make a web request to the given URL and return the response object."""
request_headers = {
+ # Override the User-Agent because our download server seems to block
+ # requests with the default UA value and responds "403 Forbidden".
"User-Agent": (
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 "
"Firefox/86.0"
@@ -26,6 +29,7 @@ def url_fetch(url, headers=None, **kwargs):
def url_exists(url):
+ """Make a HEAD request to the URL and check if the response is "200 OK"."""
try:
resp = url_fetch(url, method="HEAD")
except IOError:
@@ -34,6 +38,7 @@ def url_exists(url):
def url_download_json(url):
+ """Returns the JSON object from the given URL or return None."""
try:
resp = url_fetch(url)
manifest_data = resp.read().decode()
@@ -44,6 +49,7 @@ def url_download_json(url):
def sha256(file_path):
+ """Returns the sha256 hexdigest for a file."""
with open(file_path, mode="rb") as fp:
read_chunk = functools.partial(fp.read, 1024)
m = hashlib.sha256()
@@ -53,6 +59,7 @@ def sha256(file_path):
def find_git_branch(path="."):
+ """Return the checked out git branch for the given path."""
return subprocess.check_output(
("git", "rev-parse", "--abbrev-ref", "HEAD"),
cwd=path,
@@ -61,6 +68,11 @@ def find_git_branch(path="."):
def generate_file_metadata(file_path, destdir):
+ """
+ Generate the file metadata for file_Path.
+
+ The destdir argument is used for for generating the download URL.
+ """
file_stat = os.stat(file_path)
file_sha256 = sha256(file_path)
file_name = os.path.basename(file_path)
@@ -91,12 +103,14 @@ def generate_file_metadata(file_path, destdir):
def collect_manifest_data(job_data):
+ """Parse the job metadata dict and return the manifest data."""
job_result = job_data["result"]
print(f"Build job result: {job_result}")
assert job_result == "success"
manifest_data = {}
for output_name, output_data in job_data["outputs"].items():
+ # Filter out unrelated job outputs that don't start with "artifact-".
prefix, _, slug = output_name.partition("-")
if prefix != "artifact" or not slug:
print(f"Ignoring output '{output_name}'...")
@@ -105,9 +119,10 @@ def collect_manifest_data(job_data):
url = artifact_data["file_url"]
+ # Make sure that the file actually exists on the download server
resp = url_fetch(url, method="HEAD")
if not resp.status == 200:
- raise LookupError(f"Unable to find URL '{url}' on remove server")
+ raise LookupError(f"Unable to find URL '{url}' on remote server")
manifest_data[slug] = artifact_data
@@ -138,32 +153,41 @@ def main(argv=None):
)
if args.cmd == "artifact":
+ # Check that we have exactly one file artifact
artifact_paths = glob.glob(args.file)
assert len(artifact_paths) == 1
file_path = artifact_paths[0]
+ # Generate metadata and print it
metadata = generate_file_metadata(file_path, destdir)
print(json.dumps(metadata, indent=2, sort_keys=True))
if os.getenv("CI") == "true":
+ # Set GitHub Actions job output
print(
"::set-output name=artifact-{}::{}".format(
args.slug, json.dumps(metadata)
)
)
+
+ # Set the DEPLOY_DIR variable for the next build step
url = urllib.parse.urlparse(metadata["file_url"])
deploy_dir = posixpath.dirname(url.path)
with open(os.environ["GITHUB_ENV"], mode="a") as fp:
fp.write(f"DEPLOY_DIR={deploy_dir}\n")
elif args.cmd == "manifest":
+ # Parse the JOB_DATA JSON data, generate the manifest data and print it
job_data = json.loads(os.environ["JOB_DATA"])
manifest_data = collect_manifest_data(job_data)
print(json.dumps(manifest_data, indent=2, sort_keys=True))
+ # Write the manifest.json for subsequent deployment to the server
with open("manifest.json", mode="w") as fp:
json.dump(manifest_data, fp, indent=2, sort_keys=True)
if os.getenv("CI") == "true":
+ # Check if generated manifest.json file differs from the one that
+ # is currently deployed.
manifest_url = os.environ["MANIFEST_URL"].format(
git_branch=git_branch
)
@@ -175,6 +199,8 @@ def main(argv=None):
if manifest_data == remote_manifest_data:
return
+ # The manifest data is different, so we set the DEPLOY_DIR and
+ # MANIFEST_DIRTY env vars.
deploy_dir = os.environ["DESTDIR"].format(git_branch=git_branch)
with open(os.environ["GITHUB_ENV"], mode="a") as fp:
fp.write(f"DEPLOY_DIR={deploy_dir}\n")