-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat/migrate git logic to python (#5)
* feat(action): Add configuration provider * feat(vscode): Change auto save to onFocusChange since ruff does not work with afterDelay. * feat(vscode): Add test task * refac(tests): Remove __main__.py tests * feat(vscode): Exclude __pycache__ folders in workspace * refac(ActionConfig): Remove default value for registry_domain * feat(git): Add git helper * refac(action): Pass configuration over env. instead of cli args. * refac(action): Add git handling and use new configuration provider. * refac(action_integration_test): Provider github token in env. instead of input. * fix(action): Remove git logic and rename env vars * feat(ActionConfig): Log substring of secrets * fix(ConfigProvider): Make flag registry_secrets as secret. * refac(action): Change github_token back to input variable. * fix(action): Add exception handling if target branch does not exist * fix(config): Fix conversion from env_string to bool. * refac(cli): Move cli resources to __main__ * feat(action): Add input to set relative working dir. * feat(git): Set git root to new repo_root value. * doc(README): Update documentation of the github action.
- Loading branch information
Showing
13 changed files
with
361 additions
and
213 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,21 +22,20 @@ inputs: | |
description: "Git email to use for commits. Defaults to [email protected]" | ||
required: false | ||
default: "[email protected]" | ||
github_token: | ||
description: "GitHub access token. Defaults to github.token." | ||
default: ${{ github.token }} | ||
report_only: | ||
description: "Only report new versions. Do not update files. Defaults to false" | ||
default: "false" | ||
required: true | ||
registry_secrets: | ||
description: "Registry secrets to use for private registries" | ||
description: "Registry secrets to use for private registries. Needs to be a newline separated list of secrets in the format <registry_domain>:<secret_name>. Defaults to empty" | ||
required: false | ||
default: "" | ||
working_directory: | ||
description: "Working directory to run the command in. Defaults to the root of the repository" | ||
working_directory_relative: | ||
description: "Working directory to run the action in. Defaults to the root of the repository" | ||
required: false | ||
default: ${{ github.workspace }} | ||
github_token: | ||
description: "GitHub access token. Defaults to github.token." | ||
default: ${{ github.token }} | ||
outputs: | ||
target_branch: | ||
description: "Name of the branch where changes will be pushed to" | ||
|
@@ -70,39 +69,13 @@ runs: | |
pip install -r requirements.txt | ||
shell: bash | ||
|
||
- name: Create target branch | ||
id: create_branch | ||
if: ${{ inputs.report_only == 'false' }} | ||
uses: peterjgrainger/[email protected] | ||
env: | ||
GITHUB_TOKEN: ${{ inputs.github_token }} | ||
with: | ||
branch: "refs/heads/${{ inputs.target_branch_name }}" | ||
|
||
- name: Configure git | ||
if: ${{ inputs.report_only }} == 'false' }} | ||
working-directory: ${{ inputs.working_directory }} | ||
shell: bash | ||
run: | | ||
git config --global user.name "${{ inputs.git_user }}" | ||
git config --global user.email "${{ inputs.git_email }}" | ||
- name: Switch to target branch | ||
if: ${{ inputs.report_only == 'false' }} | ||
working-directory: ${{ inputs.working_directory }} | ||
shell: bash | ||
run: | | ||
git fetch origin | ||
git checkout -b "${{ steps.branch.outputs.target }}" "${{ steps.branch.outputs.target_origin }}" | ||
- name: Rebase target branch | ||
if: ${{ steps.create_branch.outputs.created == 'false' }} | ||
working-directory: ${{ inputs.working_directory }} | ||
shell: bash | ||
run: | | ||
echo "Rebasing ${{ steps.branch.outputs.target }} on ${{ steps.branch.outputs.head_origin }}" | ||
git rebase -Xtheirs ${{ steps.branch.outputs.head_origin }} | ||
- name: Run InfraPatch Action | ||
shell: bash | ||
run: | | ||
|
@@ -111,17 +84,17 @@ runs: | |
if [ "${{ runner.debug }}" == "1" ]; then | ||
arguments+=("--debug") | ||
fi | ||
if [ "${{ inputs.report_only }}" == "true" ]; then | ||
arguments+=("--report-only") | ||
fi | ||
if [ "${{ inputs.registry_secrets }}" != "" ]; then | ||
arguments+=("--registry-secrets-string" "\"${{ inputs.registry_secrets }}\"") | ||
fi | ||
arguments+=("--github-token" "${{ inputs.github_token }}") | ||
arguments+=("--head-branch" "${{ steps.branch.outputs.head }}") | ||
arguments+=("--target-branch" "${{ steps.branch.outputs.target }}") | ||
arguments+=("--repository-name" "${{ inputs.repository_name }}") | ||
arguments+=("--working-directory" "${{ inputs.working_directory }}") | ||
arguments+=("--default-registry-domain" "${{ inputs.default_registry_domain }}") | ||
python -m "$module" "${arguments[@]}" | ||
env: | ||
# Config from inputs | ||
GITHUB_TOKEN: ${{ inputs.github_token }} | ||
DEFAULT_REGISTRY_DOMAIN: ${{ inputs.DEFAULT_REGISTRY_DOMAIN }} | ||
REPOSITORY_NAME: ${{ inputs.repository_name }} | ||
REPORT_ONLY: ${{ inputs.report_only }} | ||
REGISTRY_SECRET_STRING: ${{ inputs.REGISTRY_SECRETS }} | ||
WORKING_DIRECTORY_RELATIVE: ${{ inputs.working_directory_relative }} | ||
|
||
# Calculated config from other steps | ||
HEAD_BRANCH: ${{ steps.branch.outputs.head }} | ||
TARGET_BRANCH: ${{ steps.branch.outputs.target }} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import os | ||
from pathlib import Path | ||
from typing import Any | ||
import logging as log | ||
|
||
|
||
class MissingConfigException(Exception): | ||
pass | ||
|
||
|
||
class ActionConfigProvider: | ||
github_token: str | ||
head_branch: str | ||
target_branch: str | ||
repository_name: str | ||
default_registry_domain: str | ||
working_directory: Path | ||
repository_root: Path | ||
report_only: bool | ||
registry_secrets: dict[str, str] | ||
|
||
def __init__(self) -> None: | ||
self.github_token = _get_value_from_env("GITHUB_TOKEN", secret=True) | ||
self.head_branch = _get_value_from_env("HEAD_BRANCH") | ||
self.target_branch = _get_value_from_env("TARGET_BRANCH") | ||
self.repository_name = _get_value_from_env("REPOSITORY_NAME") | ||
self.repository_root = Path(os.getcwd()) | ||
self.working_directory = self.repository_root.joinpath(_get_value_from_env("WORKING_DIRECTORY_RELATIVE", default="")) | ||
self.default_registry_domain = _get_value_from_env("DEFAULT_REGISTRY_DOMAIN") | ||
self.registry_secrets = _get_credentials_from_string(_get_value_from_env("REGISTRY_SECRET_STRING", secret=True, default="")) | ||
self.report_only = _from_env_to_bool(_get_value_from_env("REPORT_ONLY", default="False").lower()) | ||
|
||
|
||
def _get_value_from_env(key: str, secret: bool = False, default: Any = None) -> Any: | ||
if key in os.environ: | ||
log_value = os.environ[key] | ||
if secret: | ||
log_value = f"{log_value[:3]}***" | ||
log.debug(f"Found the following value for {key}: {log_value}") | ||
return os.environ[key] | ||
if default is not None: | ||
log.debug(f"Using default value for {key}: {default}") | ||
return default | ||
raise MissingConfigException(f"Missing configuration for key: {key}") | ||
|
||
|
||
def _get_credentials_from_string(credentials_string: str) -> dict[str, str]: | ||
credentials = {} | ||
if credentials_string == "": | ||
return credentials | ||
for line in credentials_string.splitlines(): | ||
try: | ||
name, token = line.split("=", 1) | ||
except ValueError as e: | ||
log.debug(f"Secrets line '{line}' could not be split into name and token.") | ||
raise Exception(f"Error processing secrets: '{e}'") | ||
# add the name and token to the credentials dict | ||
credentials[name] = token | ||
return credentials | ||
|
||
|
||
def _from_env_to_bool(value: str) -> bool: | ||
return value.lower() in ["true", "1", "yes", "y", "t"] |
Oops, something went wrong.