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
2 changes: 1 addition & 1 deletion .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
run: sed -i 's@'$GITHUB_WORKSPACE'@/github/workspace/@g' coverage.xml

- name: SonarCloud Scan
uses: sonarsource/sonarqube-scan-action@v7.0.0
uses: sonarsource/sonarqube-scan-action@v8.0.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
if: env.SONAR_TOKEN != ''
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sonar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
run: sed -i 's@'$GITHUB_WORKSPACE'@/github/workspace/@g' coverage.xml

- name: SonarCloud Scan
uses: sonarsource/sonarqube-scan-action@v7.0.0
uses: sonarsource/sonarqube-scan-action@v8.0.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
if: env.SONAR_TOKEN != ''
Expand Down
19 changes: 18 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,22 @@
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.envFile": "${workspaceFolder}/.test.env"
"pylint.ignorePatterns": ["**/tests/**"],
"pylint.args": [
// broad-exception-caught
"--disable=W0718",
// missing-module-docstring
"--disable=C0114",
// missing-class-docstring
"--disable=C0115",
// too-few-public-methods
"--disable=R0903",
// line-too-long
"--disable=C0301",
// abstract-method
"--disable=W0223",
],
"python.envFile": "${workspaceFolder}/.test.env",
"python-envs.defaultEnvManager": "ms-python.python:pipenv",
"files.trimTrailingWhitespace": true
}
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name = "pypi"
[packages]
slack-bolt = "==1.28.0"
python-dotenv = "==1.2.2"
gunicorn = "==25.3.0"
gunicorn = "==26.0.0"
flask = "==3.1.3"
requests = "==2.33.1"
pyjwt = "==2.12.1"
Expand Down
8 changes: 4 additions & 4 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
# Register App Events
request_change_handler.register_events(app)

# Register App APIs
# Register App APIs
slack_app = slack_handler.register_handler(app)

if __name__ == "__main__":
slack_app.run()
slack_app.run()
31 changes: 17 additions & 14 deletions src/controller/change_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
populate_selection,
populate_metadata,
populate_selection_status,
prepare_body,
prepare_body,
get_status,
get_state_value,
get_state_name,
Expand All @@ -33,7 +33,7 @@ def on_domain_selected(ack, body, client, logger):
team_id = body["team"]["id"]
domain_id = get_selected_action(body)
domain_name = get_selected_action_text(body)

envs = SwitcherService().get_environments(team_id, domain_id or "") or []

# Clear previous selection
Expand All @@ -48,7 +48,7 @@ def on_domain_selected(ack, body, client, logger):
values = get_environment_keyval(envs)
)

populate_metadata(body["view"], {
populate_metadata(body["view"], {
"domain_id": domain_id,
"domain_name": domain_name
})
Expand Down Expand Up @@ -94,7 +94,7 @@ def on_environment_selected(ack, body, client, logger):
item = "Group",
values = get_keyval("name", groups)
)

# Push changes to view
view_hash = body["view"]["hash"]
view_id = body["view"]["id"]
Expand Down Expand Up @@ -225,18 +225,18 @@ def on_change_request_review(ack, body, client, view, logger):
user_message = ":large_green_square: *Request does not require approval*: Updated with success!"
elif result == 'FROZEN_ENVIRONMENT':
user_message = ":large_red_square: *Request cannot be made*: Environment is frozen."

if user_message is not None:
client.chat_postMessage(
channel = user["id"],
text = "Change Request Review",
blocks = create_block_message(user_message)
)

return view, user_message
except Exception as e:
client.chat_postMessage(
channel = user["id"],
channel = user["id"],
text = f"There was an error with your request: {e}"
)

Expand All @@ -250,7 +250,7 @@ def on_submit(ack, body, client, logger):
ack()
user = body["user"]
team_id = body["team"]["id"]

try:
# Collect args
observation = get_state_value(body["view"], "selection_observation")
Expand Down Expand Up @@ -286,10 +286,11 @@ def on_submit(ack, body, client, logger):
except Exception as e:
logger.error(f"Error on submitting: {e}")
client.chat_postMessage(
channel = user["id"],
channel = user["id"],
text = f"There was an error with your request: {e}"
)

return e

def on_change_request_abort(ack, body, client):
""" Return to home view """

Expand All @@ -303,7 +304,7 @@ def on_change_request_abort(ack, body, client):

def on_request_approved(ack, body, client, logger):
""" Approve ticket through Switcher API and update chat message """

ack()
message_ts = body["message"]["ts"]
team_id = body["team"]["id"]
Expand Down Expand Up @@ -335,10 +336,11 @@ def on_request_approved(ack, body, client, logger):
ts = message_ts,
blocks = create_block_message(f":large_yellow_square: *{e.args[0]}*")
)
return e

def on_request_denied(ack, body, client, logger):
""" Deny ticket through Switcher API and update chat message """

ack()
message_ts = body["message"]["ts"]
team_id = body["team"]["id"]
Expand All @@ -360,7 +362,7 @@ def on_request_denied(ack, body, client, logger):
ts = message_ts,
blocks = message_blocks
)

return message_blocks
except Exception as e:
logger.error(f"Error on denying: {e}")
Expand All @@ -369,4 +371,5 @@ def on_request_denied(ack, body, client, logger):
text = e.args[0],
ts = message_ts,
blocks = create_block_message(f":large_yellow_square: *{e.args[0]}*")
)
)
return e
3 changes: 2 additions & 1 deletion src/controller/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ def on_change_request_opened(ack, body, client, logger):

return change_request
except Exception as e:
logger.error(f"Error opening change request form: {e}")
logger.error(f"Error opening change request form: {e}")
return None
17 changes: 8 additions & 9 deletions src/controller/slack_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
from slack_bolt.adapter.flask import SlackRequestHandler
from slack_sdk.oauth.state_store import FileOAuthStateStore

from flask import Flask, request, session, make_response
from flask import Flask, request

from utils.constants import SWITCHER_URL, SWITCHER_API_URL, VERSION
from store.switcher_store import SwitcherAppInstallationStore

class SlackAppHandler:
def build_app(self, api_url: str = os.environ.get("SWITCHER_API_URL") or "") -> App:
""" Build the Slack App Settings """

return App(
signing_secret = os.environ.get("SLACK_SIGNING_SECRET"),
installation_store = SwitcherAppInstallationStore(api_url),
Expand Down Expand Up @@ -66,12 +66,10 @@ def oauth_redirect():
return flask_app

def success(self, args: SuccessArgs) -> BoltResponse:
""" Handles the redirection from Slack's OAuth flow when the installation is successful """
assert args.request is not None
t_id = args.installation.team_id
e_id = args.installation.enterprise_id

if e_id is None: e_id = ""
if t_id is None: t_id = ""
t_id = args.installation.team_id if args.installation.team_id is not None else ""
e_id = args.installation.enterprise_id if args.installation.enterprise_id is not None else ""

return BoltResponse(
status = 308,
Expand All @@ -81,6 +79,7 @@ def success(self, args: SuccessArgs) -> BoltResponse:
)

def failure(self, args: FailureArgs) -> BoltResponse:
""" Handles the redirection from Slack's OAuth flow when the installation fails """
assert args.request is not None
assert args.reason is not None

Expand All @@ -89,4 +88,4 @@ def failure(self, args: FailureArgs) -> BoltResponse:
headers = {
"Location": f"{SWITCHER_URL}/slack/authorization?error=1&reason={args.reason}",
}
)
)
6 changes: 3 additions & 3 deletions src/errors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ class SwitcherContextError(SwitcherSlackAppError):
def __init__(self, missing: list[str]):
attributes = " - ".join([str(elem) for elem in missing])
msg = f"Missing [{attributes}]"
super(SwitcherContextError, self).__init__(msg)
super().__init__(msg)

class SwitcherValidationError(SwitcherSlackAppError):
""" Error raised when ticket has issues and cannot be opened """

def __init__(self, message: str):
message = "Try it again later" if message is None else message
super(SwitcherValidationError, self).__init__(message)
super().__init__(message)

class SwitcherSlackInstallationError(SwitcherSlackAppError):
""" Error raised when slack installation fails """

def __init__(self, message: str):
super(SwitcherSlackInstallationError, self).__init__(message)
super().__init__(message)
16 changes: 8 additions & 8 deletions src/events/request_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RequestChangeEventHandler:
def register_events(self, app):
""" Register events for the Request Change feature """

# Show the app landing page
# Show the app landing page
@app.event("app_home_opened")
def app_home_opened(client, event, logger):
on_home_opened(client, event, logger)
Expand All @@ -34,20 +34,20 @@ def selection_domain(ack, body, client, logger):
@app.action("selection_environment")
def selection_environment(ack, body, client, logger):
on_environment_selected(ack, body, client, logger)

# Update Change Request modal with available group switchers
@app.action("selection_group")
def selection_group(ack, body, client, view, logger):
def selection_group(ack, body, client, logger):
on_group_selected(ack, body, client, logger)

# Update Change Request modal with status options
@app.action("selection_switcher")
def selection_switcher(ack, body, client, logger):
def selection_switcher(ack, body, client):
on_switcher_selected(ack, body, client)

# Confirm status selection
@app.action("selection_status")
def selection_status(ack, body, client, logger):
def selection_status(ack):
ack()

# Submit Change Request for review
Expand All @@ -57,12 +57,12 @@ def handle_change_request_review(ack, body, client, view, logger):

# Submit Change Request for verification and approval
@app.action("change_request_submit")
def handle_submission(ack, body, client, view, logger):
def handle_submission(ack, body, client, logger):
on_submit(ack, body, client, logger)

# Abort Change Request
@app.action("change_request_abort")
def handle_change_request_abort(ack, body, client, view, logger):
def handle_change_request_abort(ack, body, client):
on_change_request_abort(ack, body, client)

# Request approved
Expand All @@ -73,4 +73,4 @@ def request_approved(ack, body, client, logger):
# Request denied
@app.action("request_denied")
def request_denied(ack, body, client, logger):
on_request_denied(ack, body, client, logger)
on_request_denied(ack, body, client, logger)
Loading