stash/restore/get_stash.py (55 lines of code) (raw):
# Copyright (c) The stash contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import subprocess
from typing import List
def print_debug(msg: str):
"""Print a message that is only visible when the GHA debug flag is set."""
print(f"::debug::{msg}")
def set_output(name: str, value: str):
"""Set a GHA output variable."""
with open(ensure_env_var("GITHUB_OUTPUT"), "a") as f:
f.write(f"{name}={value}\n")
def ensure_env_var(var: str) -> str:
"""Return value of envvar `var`, throw if it's not set."""
value = os.environ.get(var)
if value is None or len(value) == 0:
raise ValueError(f"Environment variable {var} is not set")
return value
def run_checked(args, **kwargs):
"""Run command and capture it's output and check that it exits successfully."""
result = subprocess.run(args, **kwargs, capture_output=True, check=True, text=True)
return result
def jq(file: str, query: str, args: List[str] = []):
"""Wrapper to run `jq` query on a file on disk or on a JSON string."""
if os.path.isfile(file):
result = run_checked(["jq", *args, query, file])
elif file.startswith("{"):
result = run_checked(["jq", *args, query], input=file)
else:
raise ValueError("Input 'file' not found and not valid json string")
return result
def gh_api(endpoint: str, method: str = "get", options: List[str] = []):
"""Wrapper to run `gh` REST API calls."""
args = [
"gh",
"api",
"-H",
"Accept: application/vnd.github+json",
"-H",
"X-GitHub-Api-Version: 2022-11-28",
f"--method={method}",
*options,
endpoint,
]
result = run_checked(args)
return result
def ensure_json(output: str):
"""Always return valid JSON."""
if output.isspace():
return json.loads("{}")
else:
return json.loads(output)
def get_workflow_stash(repo: str, run_id: str, name: str):
ops = ["-q", ".artifacts | max_by(.updated_at | fromdate)", "-f", f"name={name}"]
res = gh_api(f"repos/{repo}/actions/runs/{run_id}/artifacts", options=ops)
print_debug(f"Returned stash: {res.stdout}")
return ensure_json(res.stdout)
def get_branch_stash(repo: str, name: str, branch: str, repo_id: int):
query = f"""
.artifacts | map(select(
.expired == false and
.workflow_run.head_branch == "{branch}"
and .workflow_run.head_repository_id == {repo_id}))
| max_by(.updated_at | fromdate)
"""
ops = ["-q", query, "-f", f"name={name}"]
res = gh_api(f"repos/{repo}/actions/artifacts", options=ops)
print_debug(f"Returned stash: {res.stdout}")
return ensure_json(res.stdout)