Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Add new ``github.create_repository_from_template`` action which allows user to create a repository from template.
* Bug fix on ``github.store_oauth_token.`` to api save the token correctly so that it can be read later.
* Segure improvement on ``github.store_oauth_token.`` to encrypt de github token in web interface.
* Add new ``github.create_branch``, ``github.get_branch``, ``github.delete_branch`` actions which allows user to create/get/delete a branch.

## 2.1.1

Expand Down
29 changes: 29 additions & 0 deletions actions/add_update_repository_team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import time
import datetime


from lib.base import BaseGithubAction

__all__ = [
'AddUpdateRepositoryTeamAction'
]

class AddUpdateRepositoryTeamAction(BaseGithubAction):
def run(self, api_user, org, team_slug, owner, repo, github_type, permission ):

enterprise = self._is_enterprise(github_type)

if api_user:
self.token = self._get_user_token(api_user, enterprise)

payload = { "permission": permission }

response = self._request("PUT",
"/orgs/{}/teams/{}/repos/{}/{}".format(org,team_slug,owner,repo ),
payload,
self.token,
enterprise)

results = {'response': response}

return results
48 changes: 48 additions & 0 deletions actions/add_update_repository_team.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
name: add_update_repository_team
runner_type: python-script
pack: github
description: >
Add or update repository team.
Example:
st2 run github.add_update_repository_team organization="organization" owner="owner" repo="reponame" team_slug="team_id" api_user="token_name"
enabled: true
entry_point: add_update_repository_team.py
parameters:
api_user:
type: "string"
description: "The API user"
default: "{{action_context.api_user|default(None)}}"
org:
type: "string"
description: "The organization name. The name is not case sensitive."
required: true
team_slug:
type: "string"
description: "The slug of the team name."
required: true
owner:
type: "string"
description: "The account owner of the repository. The name is not case sensitive."
required: true
repo:
type: "string"
description: "The name of the repository. The name is not case sensitive."
required: true
github_type:
type: "string"
description: "The type of github installation to target, if unset will use the configured default."
enum:
- "online"
- "enterprise"
default: "enterprise"
permission:
type: "string"
description: "The permission to grant the team on this repository. In addition to the enumerated values, you can also specify a custom repository role name, if the owning organization has defined any. If no permission is specified, the team's permission attribute will be used to determine what permission to grant the team on this repository."
enum:
- "pull"
- "push"
- "admin"
- "maintain"
- "triage"
default: "push"
40 changes: 40 additions & 0 deletions actions/create_branch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import time
import datetime


from lib.base import BaseGithubAction

__all__ = [
'CreateBranchAction'
]

class CreateBranchAction(BaseGithubAction):
def run(self, api_user, new_branch, origin_ref, repository, github_type):

enterprise = self._is_enterprise(github_type)

if api_user:
self.token = self._get_user_token(api_user, enterprise)


# First, we have to get the sha1 for the given origin ref
response = self._request("GET", f"/repos/{repository}/git/ref/{origin_ref}",
{},
self.token,
enterprise)

if not response or not response['object']['sha']:
raise Exception(f"Could not get ref [{origin_ref}]. Response: {response}")


# Then, we create the branch based on the origin ref
payload = { "ref": f"refs/heads/{new_branch}",
"sha": response['object']['sha']}

response = self._request("POST",
f"/repos/{repository}/git/refs",
payload,
self.token,
enterprise)

return { 'response': response }
32 changes: 32 additions & 0 deletions actions/create_branch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: "create_branch"
runner_type: "python-script"
description: >
Create a new branch for a GitHub repository
Example:
st2 run github.create_branch repository="reponame" origin_ref="heads/<branch>" new_branch="branch_name" api_user="token_name"
enabled: true
entry_point: "create_branch.py"
parameters:
api_user:
type: "string"
description: "The API user"
default: "{{action_context.api_user|default(None)}}"
repository:
type: "string"
description: "The full (Organization|User)/repository path"
required: true
origin_ref:
type: "string"
description: "The current reference to branch from (e.g. heads/master, heads/main)"
default: "heads/master"
new_branch:
type: "string"
description: "The branch to be created from the given ref"
github_type:
type: "string"
description: "The type of github installation to target, if unset will use the configured default."
default: enterprise
enum:
- enterprise
- online
3 changes: 2 additions & 1 deletion actions/create_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@


class CreateFileAction(BaseGithubAction):
def run(self, user, repo, path, message, content, branch=None, committer=None, author=None,
def run(self, user, repo, path, message, content, github_type, api_user, branch=None, committer=None, author=None,
encoding=None):
self._change_to_user_token_if_enterprise(api_user, github_type)
author, branch, committer = prep_github_params_for_file_ops(author, branch, committer)

if encoding and encoding == 'base64':
Expand Down
12 changes: 12 additions & 0 deletions actions/create_file.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,15 @@ parameters:
type: "string"
description: "If omitted this will be filled in with committer information. If passed, you must specify both a name and email. Expected format: FirstName LastName <email@address>"
required: false

api_user:
type: "string"
description: "The"
default: "{{action_context.api_user|default(None)}}"
github_type:
type: "string"
description: "The type of github installation to target, if unset will use the configured default."
default: ~
enum:
- enterprise
- online
4 changes: 3 additions & 1 deletion actions/create_pull.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@


class CreatePullAction(BaseGithubAction):
def run(self, user, repo, title, body, head, base):
def run(self, user, repo, title, body, head, base, api_user, github_type):
self._change_to_user_token_if_enterprise(api_user, github_type)

user = self._client.get_user(user)
repo = user.get_repo(repo)
pull = repo.create_pull(title=title, body=body, head=head, base=base)
Expand Down
12 changes: 12 additions & 0 deletions actions/create_pull.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,15 @@ parameters:
type: "string"
description: "The name of the branch you want the changes pulled into. This should be an existing branch on the current repository. You cannot submit a pull request to one repository that requests a merge to a base of another repository."
required: true
api_user:
type: "string"
description: "The"
default: "{{action_context.api_user|default(None)}}"
github_type:
type: "string"
description: "The type of github installation to target, if unset will use the configured default."
default: ~
enum:
- enterprise
- online

24 changes: 24 additions & 0 deletions actions/delete_branch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import time
import datetime


from lib.base import BaseGithubAction

__all__ = [
'DeleteBranchAction'
]

class DeleteBranchAction(BaseGithubAction):
def run(self, api_user, branch, repository, github_type):

enterprise = self._is_enterprise(github_type)

if api_user:
self.token = self._get_user_token(api_user, enterprise)

response = self._request("DELETE", f"/repos/{repository}/git/refs/heads/{branch}",
{},
self.token,
enterprise)

return { 'response': response }
28 changes: 28 additions & 0 deletions actions/delete_branch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: "delete_branch"
runner_type: "python-script"
description: >
Deletes a branch from a GitHub repository
Example:
st2 run github.delete_branch repository="reponame" branch="branch_name" api_user="token_name"
enabled: true
entry_point: "delete_branch.py"
parameters:
api_user:
type: "string"
description: "The API user"
default: "{{action_context.api_user|default(None)}}"
repository:
type: "string"
description: "The full (Organization|User)/repository path"
required: true
branch:
type: "string"
description: "The branch to be created from the given ref"
github_type:
type: "string"
description: "The type of github installation to target, if unset will use the configured default."
default: enterprise
enum:
- enterprise
- online
26 changes: 26 additions & 0 deletions actions/get_branch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import time
import datetime


from lib.base import BaseGithubAction

__all__ = [
'GetBranchAction'
]

class GetBranchAction(BaseGithubAction):
def run(self, api_user, branch, repository, github_type):

enterprise = self._is_enterprise(github_type)

if api_user:
self.token = self._get_user_token(api_user, enterprise)


# First, we have to get the sha1 for the given origin ref
response = self._request("GET", f"/repos/{repository}/git/ref/heads/{branch}",
{},
self.token,
enterprise)

return { 'response': response }
28 changes: 28 additions & 0 deletions actions/get_branch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: "get_branch"
runner_type: "python-script"
description: >
Gets branch details from a GitHub repository
Example:
st2 run github.get_branch repository="reponame" branch="branch_name" api_user="token_name"
enabled: true
entry_point: "get_branch.py"
parameters:
api_user:
type: "string"
description: "The API user"
default: "{{action_context.api_user|default(None)}}"
repository:
type: "string"
description: "The full (Organization|User)/repository path"
required: true
branch:
type: "string"
description: "The name of the branch to fetch details for"
github_type:
type: "string"
description: "The type of github installation to target, if unset will use the configured default."
default: enterprise
enum:
- enterprise
- online
4 changes: 1 addition & 3 deletions actions/get_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

class GetUserAction(BaseGithubAction):
def run(self, user, token_user, github_type):
enterprise = self._is_enterprise(github_type)
if token_user:
self._change_to_user_token(token_user, enterprise)
self._change_to_user_token_if_enterprise(token_user, github_type)

user = self._client.get_user(user)
result = user_to_dict(user=user)
Expand Down
15 changes: 15 additions & 0 deletions actions/lib/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import requests
from bs4 import BeautifulSoup
import json
import logging

from st2common.runners.base_action import Action

Expand All @@ -18,6 +19,7 @@


class BaseGithubAction(Action):

def run(self, **kwargs):
pass

Expand Down Expand Up @@ -70,6 +72,8 @@ def _get_analytics(self, category, repo, enterprise):
response = s.get(url)
return response.json()

# Whether or not this execution is meant for enterprise github installation (on-premises)
# or online installations (in the cloud)
def _is_enterprise(self, github_type):

if github_type == "enterprise":
Expand All @@ -83,6 +87,8 @@ def _is_enterprise(self, github_type):
else:
raise ValueError("Default GitHub Invalid!")

# Github token will come from KV using this function.. and depending on whether
# it's for enterprise or not, it will return have either of the key prefix below
def _get_user_token(self, user, enterprise):
"""
Return a users GitHub OAuth Token, if it fails replace '-'
Expand All @@ -104,7 +110,15 @@ def _get_user_token(self, user, enterprise):

return token

def _change_to_user_token_if_enterprise(self, api_user, github_type):
enterprise = self._is_enterprise(github_type)
if api_user:
self._change_to_user_token(api_user, enterprise)

# Changes the internal client used on this instance of action execution to
# the one matching the configuration for enterprise/online and user given here
def _change_to_user_token(self, user, enterprise):
logging.debug("Changing github client for user [%s] and enterprise [%s]", user, enterprise)
token = self._get_user_token(user, enterprise)

if enterprise:
Expand All @@ -114,6 +128,7 @@ def _change_to_user_token(self, user, enterprise):

return True

# Sends a generic HTTP/s request to the github endpoint
def _request(self, method, uri, payload, token, enterprise):
headers = {'Authorization': 'token {}'.format(token)}

Expand Down
Loading