Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache github token for up with --repo #91

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/containerapp/azext_containerapp/_github_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
# --------------------------------------------------------------------------------------------
# pylint: disable=consider-using-f-string

import os
import json
from datetime import datetime

from azure.cli.core.util import open_page_in_browser
from azure.cli.core.auth.persistence import SecretStore, build_persistence
from azure.cli.core.azclierror import (ValidationError, CLIInternalError, UnclassifiedUserFault)
from ._utils import repo_url_to_name
from knack.log import get_logger

logger = get_logger(__name__)
Expand All @@ -25,6 +31,43 @@
]


def _get_github_token_secret_store(cmd):
location = os.path.join(cmd.cli_ctx.config.config_dir, "github_token_cache")
file_persistence = build_persistence(location, encrypt=True)
return SecretStore(file_persistence)


def cache_github_token(cmd, token, repo):
repo = repo_url_to_name(repo)
secret_store = _get_github_token_secret_store(cmd)
cache = secret_store.load()

for entry in cache:
if isinstance(entry, dict) and entry.get("value") == token:
if repo not in entry.get("repos", []):
entry["repos"] = [*entry.get("repos", []), repo]
entry["last_modified_timestamp"] = datetime.utcnow().timestamp()
break
else:
cache_entry = {"last_modified_timestamp": datetime.utcnow().timestamp(), "value": token, "repos": [repo]}
cache = [cache_entry, *cache]

secret_store.save(cache)


def load_github_token_from_cache(cmd, repo):
repo = repo_url_to_name(repo)
secret_store = _get_github_token_secret_store(cmd)
cache = secret_store.load()

if isinstance(cache, list):
for entry in cache:
if isinstance(entry, dict) and repo in entry.get("repos", []):
return entry.get("value")

return None


def get_github_access_token(cmd, scope_list=None, token=None): # pylint: disable=unused-argument
if token:
return token
Expand Down
13 changes: 13 additions & 0 deletions src/containerapp/azext_containerapp/_up_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
create_or_update_github_action,
)

from ._github_oauth import load_github_token_from_cache, get_github_access_token

logger = get_logger(__name__)


Expand Down Expand Up @@ -865,3 +867,14 @@ def check_env_name_on_rg(cmd, managed_env, resource_group_name, location):
if env_def:
if location != env_def["location"]:
raise ValidationError("Environment {} already exists in resource group {} on location {}, cannot change location of existing environment to {}.".format(parse_resource_id(managed_env)["name"], resource_group_name, env_def["location"], location))


def get_token(cmd, repo, token):
if not repo:
return None
if token:
return token
token = load_github_token_from_cache(cmd, repo)
if not token:
token = get_github_access_token(cmd, ["admin:repo_hook", "repo", "workflow"], token)
return token
2 changes: 1 addition & 1 deletion src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def await_github_action(cmd, token, repo, branch, name, resource_group_name, tim

def repo_url_to_name(repo_url):
repo = None
repo = repo_url.split('/')
repo = [s for s in repo_url.split('/') if s]
if len(repo) >= 2:
repo = '/'.join(repo[-2:])
return repo
Expand Down
6 changes: 4 additions & 2 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,8 @@ def containerapp_up(cmd,
from ._up_utils import (_validate_up_args, _reformat_image, _get_dockerfile_content, _get_ingress_and_target_port,
ResourceGroup, ContainerAppEnvironment, ContainerApp, _get_registry_from_app,
_get_registry_details, _create_github_action, _set_up_defaults, up_output, AzureContainerRegistry,
check_env_name_on_rg)
check_env_name_on_rg, get_token)
from ._github_oauth import cache_github_token, load_github_token_from_cache
HELLOWORLD = "mcr.microsoft.com/azuredocs/containerapps-helloworld"
dockerfile = "Dockerfile" # for now the dockerfile name must be "Dockerfile" (until GH actions API is updated)

Expand All @@ -2026,7 +2027,7 @@ def containerapp_up(cmd,
check_env_name_on_rg(cmd, managed_env, resource_group_name, location)

image = _reformat_image(source, repo, image)
token = None if not repo else get_github_access_token(cmd, ["admin:repo_hook", "repo", "workflow"], token)
token = get_token(cmd, repo, token)

if image and HELLOWORLD in image.lower():
ingress = "external" if not ingress else ingress
Expand Down Expand Up @@ -2066,6 +2067,7 @@ def containerapp_up(cmd,
if repo:
_create_github_action(app, env, service_principal_client_id, service_principal_client_secret,
service_principal_tenant_id, branch, token, repo, context_path)
cache_github_token(cmd, token, repo)

if browse:
open_containerapp_in_browser(cmd, app.name, app.resource_group.name)
Expand Down