Skip to content

Commit

Permalink
Merge 97aa1af into 11f28e0
Browse files Browse the repository at this point in the history
  • Loading branch information
CasperWA authored Oct 30, 2023
2 parents 11f28e0 + 97aa1af commit a37e43d
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ All input names in **bold** are _required_.
| `unprotect_reviews` | Momentarily remove pull request review protection from target branch.<br>**Note**: One needs administrative access to the repository to be able to use this feature. This means two things need to match up: The PAT must represent a user with administrative rights, and these rights need to be granted to the usage scope of the PAT. | `False` |
| `debug` | Set `set -x` in `entrypoint.sh` when running the action. This is for debugging the action. | `False` |
| `path` | A path to the working directory of the action. This should be relative to the `$GITHUB_WORKSPACE`. | `.` |
| `gh_rest_api_base_url` | The base URL for the GitHub REST API. This is useful for GitHub Enterprise users.</br>Note, `/api/v3` will be appended to this value if it does not already exist. See the note [here](https://docs.github.com/en/[email protected]/rest/quickstart?apiVersion=2022-11-28&tool=curl#using-curl-commands-in-github-actions). | `https://api.github.com` |

## License

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ inputs:
description: 'A path to the working directory of the action. This should be relative to the $GITHUB_WORKSPACE.'
required: false
default: '.'
gh_rest_api_base_url:
description: 'The base URL for the GitHub REST API. This is useful for GitHub Enterprise users. Note, `/api/v3` will be appended to this value if it does not already exist. See the note here: https://docs.github.com/en/[email protected]/rest/quickstart?apiVersion=2022-11-28&tool=curl#using-curl-commands-in-github-actions.'
required: false
default: 'https://api.github.com'
runs:
using: 'docker'
image: 'Dockerfile'
6 changes: 3 additions & 3 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ git config --global --add safe.directory ${PWD}

# Retrieve target repository
echo -e "\nFetching the latest information from '${GITHUB_REPOSITORY}' ..."
git config --local --name-only --get-regexp "http\.https\:\/\/github\.com\/\.extraheader" && git config --local --unset-all "http.https://github.com/.extraheader" || :
git submodule foreach --recursive 'git config --local --name-only --get-regexp "http\.https\:\/\/github\.com\/\.extraheader" && git config --local --unset-all "http.https://github.com/.extraheader" || :'
git remote set-url origin https://${GITHUB_ACTOR}:${INPUT_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
git config --local --name-only --get-regexp "http\.${GITHUB_SERVER_URL@Q}\/\.extraheader" && git config --local --unset-all "http.${GITHUB_SERVER_URL}/.extraheader" || :
git submodule foreach --recursive 'git config --local --name-only --get-regexp "http\.${GITHUB_SERVER_URL@Q}\/\.extraheader" && git config --local --unset-all "http.${GITHUB_SERVER_URL}/.extraheader" || :'
git remote set-url origin $(push-action --token "null" --ref "null" --temp-branch "null" -- create_origin_url)
git fetch --unshallow -tp origin || :
echo "Fetching the latest information from '${GITHUB_REPOSITORY}' ... DONE!"

Expand Down
50 changes: 47 additions & 3 deletions push_action/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
1) Get required statuses for branch (GitHub Actions jobs / third party status checks)
from:
https://api.github.com/repos/:owner/:repo/branches/:branch
{input_gh_rest_api_base_url}/repos/:owner/:repo/branches/:branch
protection -> required_status_checks -> contexts
2) Get GitHub Actions runs for specific workflow:
https://api.github.com/repos/:owner/:repo/actions/workflows/:workflow_id/runs
{input_gh_rest_api_base_url}/repos/:owner/:repo/actions/workflows/:workflow_id/runs
:workflow_id can also be :workflow_file_name (e.g., 'main.yml')
Get :run_id from this
3) Get names and statuses of jobs in specific run:
https://api.github.com/repos/:owner/:repo/actions/runs/:run_id/jobs
{input_gh_rest_api_base_url}/repos/:owner/:repo/actions/runs/:run_id/jobs
Match found required GitHub Actions runs found in 1)
4) Wait and do 3) again until required GitHub Actions jobs have "status": "completed"
Expand All @@ -29,6 +29,7 @@
import sys
from time import sleep, time
from typing import TYPE_CHECKING
from urllib.parse import urlsplit

from push_action.cache import IN_MEMORY_CACHE
from push_action.utils import (
Expand Down Expand Up @@ -197,6 +198,46 @@ def protected_branch(branch: str) -> str:
return "protected" if response["protected"] else ""


def compile_origin_url() -> str:
"""Compile the git remote 'origin' URL for the repository."""
compiled_url = ""

for required_env_vars in [
"GITHUB_SERVER_URL",
"GITHUB_REPOSITORY",
"GITHUB_ACTOR",
"INPUT_TOKEN",
]:
if required_env_vars not in os.environ:
raise RuntimeError(
f"Required rnvironment variable {required_env_vars} is not set."
)

base_url = os.getenv("GITHUB_SERVER_URL", "")
split_base_url = urlsplit(base_url)

if not split_base_url.scheme or split_base_url.netloc:
raise RuntimeError(
f"Could not determine scheme and netloc from GITHUB_SERVER_URL: {base_url}"
)

# Add scheme
compiled_url += f"{split_base_url.scheme}://"

# Add username and token
compiled_url += os.getenv("GITHUB_ACTOR", "")
compiled_url += ":"
compiled_url += os.getenv("INPUT_TOKEN", "")

# Add netloc
compiled_url += f"@{split_base_url.netloc}"

# Add path (repository)
compiled_url += f"/{os.getenv('GITHUB_REPOSITORY', '')}.git"

return compiled_url


def main() -> None:
"""Main function to run this module"""
# Handle inputs
Expand Down Expand Up @@ -247,6 +288,7 @@ def main() -> None:
"unprotect_reviews",
"protect_reviews",
"protected_branch",
"create_origin_url",
],
)

Expand All @@ -264,6 +306,8 @@ def main() -> None:
protect_reviews()
elif IN_MEMORY_CACHE["args"].ACTION == "protected_branch":
print(protected_branch(IN_MEMORY_CACHE["args"].ref), end="", flush=True)
elif IN_MEMORY_CACHE["args"].ACTION == "create_origin_url":
print(compile_origin_url(), end="", flush=True)
else:
raise RuntimeError(f"Unknown ACTIONS {IN_MEMORY_CACHE['args'].ACTION!r}")
except Exception as exc: # pylint: disable=broad-except
Expand Down
7 changes: 5 additions & 2 deletions push_action/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
import requests

from push_action.cache import IN_MEMORY_CACHE
from push_action.validate import validate_rest_api_base_url

if TYPE_CHECKING:
from typing import Callable, List, Optional, Union
from typing import Callable, List, Union


REQUEST_TIMEOUT = 10 # in seconds
API_V3_BASE = "https://api.github.com"
API_V3_BASE = validate_rest_api_base_url(os.getenv("INPUT_GH_REST_API_BASE_URL", ""))
API_VERSION = "2022-11-28"


class RepoRole(Enum):
Expand Down Expand Up @@ -73,6 +75,7 @@ def api_request(
headers={
"Authorization": f"Bearer {IN_MEMORY_CACHE['args'].token}",
"Accept": "application/vnd.github.v3+json",
"X-GitHub-Api-Version": API_VERSION,
},
timeout=REQUEST_TIMEOUT,
**kwargs,
Expand Down
40 changes: 40 additions & 0 deletions push_action/validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Validate inputs."""
from urllib.parse import urlsplit

GITHUB_FREE_REST_API_BASE_URL = "https://api.github.com"
"""Base URL for GitHub Free API."""

GITHUB_ENTERPRISE_API_PREFIX = "/api/v3"
"""Prefix for GitHub Enterprise API URLs.
See the note for more information here:
https://docs.github.com/en/[email protected]/rest/quickstart?apiVersion=2022-11-28&tool=curl#using-curl-commands-in-github-actions.
"""


def validate_rest_api_base_url(base_url: str) -> str:
"""Validate and parse the `gh_rest_api_base_url` input."""
split_base_url = urlsplit(base_url)

if not split_base_url.scheme or not split_base_url.netloc:
raise ValueError(
"Invalid URL provided for `gh_rest_api_base_url` input (missing scheme "
"and/or netloc)."
)

compiled_url = split_base_url.scheme + "://" + split_base_url.netloc

if compiled_url == GITHUB_FREE_REST_API_BASE_URL:
return compiled_url

url_path = split_base_url.path.rstrip("/")

if url_path and not split_base_url.path.endswith(GITHUB_ENTERPRISE_API_PREFIX):
raise ValueError(
"Invalid URL provided for `gh_rest_api_base_url` input (path must end with "
f"{GITHUB_ENTERPRISE_API_PREFIX!r})."
)

if not url_path:
compiled_url += GITHUB_ENTERPRISE_API_PREFIX

return compiled_url

0 comments on commit a37e43d

Please sign in to comment.