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

Present authentication issues clearly during scratch org builds #2120

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
3 changes: 2 additions & 1 deletion locales_dev/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -613,5 +613,6 @@
"walkthroughPlayMetechoName": "Metecho makes it easier for you to view, test, and contribute to Salesforce Projects without learning GitHub.<1></1><2></2><3>Pronunciation</3>: “Met” rhymes with “bet.” “Echo” as in the reflection of sound waves.<5></5><6>Definition</6>: To share or participate in.",
"walkthroughPlayScratchOrg": "This is a sample Scratch Org for this Project. Select “View Org” to see the work on this Project. Your Org will expire after 30 days.",
"walkthroughPlayScratchOrgContribute": "To contribute your own work from a Scratch Org, you need “push” permissions on the Project in GitHub. If you do not have the right permissions, ask a Project admin. Select “Contribute Work” to create a Task for your Scratch Org. When your Org expires or is deleted, any work not contributed will be lost.",
"welcomeMessage": "<0>To get started</0> log in with your GitHub account."
"welcomeMessage": "<0>To get started</0> log in with your GitHub account.",
"{{message}}. If you need support, your scratch org id is {{orgId}}.": "{{message}}. If you need support, your scratch org id is {{orgId}}."
}
3 changes: 2 additions & 1 deletion metecho/api/model_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def notify_error(self, error, *, type_=None, originating_user_id, message=None):
)

def notify_scratch_org_error(
self, *, error, type_, originating_user_id, message=None
self, *, error, type_, originating_user_id, message=None, has_build_log=False
):
"""
This is only used in the ScratchOrg model currently, but it
Expand All @@ -126,6 +126,7 @@ def notify_scratch_org_error(
type_=type_,
originating_user_id=originating_user_id,
message=message or {},
has_build_log=has_build_log,
)


Expand Down
6 changes: 5 additions & 1 deletion metecho/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,7 @@ def finalize_provision(self, *, error=None, originating_user_id):
type_="SCRATCH_ORG_PROVISION_FAILED",
originating_user_id=originating_user_id,
message=self._build_message_extras(),
has_build_log=getattr(error, "has_build_log", False),
)
# If the scratch org has already been created on Salesforce,
# we need to delete it there as well.
Expand Down Expand Up @@ -1648,7 +1649,9 @@ def remove_scratch_org(self, error, *, originating_user_id):
)
# set should_finalize=False to avoid accidentally sending a
# SCRATCH_ORG_DELETE event:
self.delete(should_finalize=False, originating_user_id=originating_user_id)
if self.config and "org_id" in self.config:
# Don't try to delete if the org doesn't exist.
self.delete(should_finalize=False, originating_user_id=originating_user_id)

def queue_refresh_org(self, *, originating_user_id):
from .jobs import refresh_scratch_org_job
Expand All @@ -1672,6 +1675,7 @@ def finalize_refresh_org(self, *, error=None, originating_user_id):
type_="SCRATCH_ORG_REFRESH_FAILED",
originating_user_id=originating_user_id,
message=self._build_message_extras(),
has_build_log=getattr(error, "has_build_log", False),
)
self.queue_delete(originating_user_id=originating_user_id)

Expand Down
3 changes: 2 additions & 1 deletion metecho/api/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async def report_error(user):


async def report_scratch_org_error(
instance, *, error, type_, originating_user_id, message=None
instance, *, error, type_, originating_user_id, has_build_log=False, message=None
):
# Unwrap the error in the case that there's only one,
# which is the most common case, per this discussion:
Expand All @@ -125,6 +125,7 @@ async def report_scratch_org_error(
"payload": {
"message": prepared_message,
"originating_user_id": originating_user_id,
"has_build_log": has_build_log,
},
}
prepared_message["payload"].update(message or {})
Expand Down
23 changes: 20 additions & 3 deletions metecho/api/sf_run_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from datetime import datetime

from cumulusci.core.config import OrgConfig, TaskConfig
from cumulusci.core.exceptions import SalesforceCredentialsException
from cumulusci.core.runtime import BaseCumulusCI
from cumulusci.oauth.client import OAuth2Client, OAuth2ClientConfig
from cumulusci.oauth.salesforce import jwt_session
Expand Down Expand Up @@ -52,13 +53,29 @@


class ScratchOrgError(Exception):
pass
has_build_log: bool

def __init__(self, message: str, has_build_log: bool):
self.has_build_log = has_build_log
super().__init__(message)


@contextlib.contextmanager
def delete_org_on_error(scratch_org=None, originating_user_id=None):
try:
yield
except ScratchOrgError:
raise
except SalesforceCredentialsException as err:
error_msg = _(
f"An authentication-related issue occured. Please report this issue to your administrator: {err.args[0]}" # noqa: B950
)
error = ScratchOrgError(error_msg, False)
if scratch_org:
scratch_org.remove_scratch_org(
error, originating_user_id=originating_user_id
)
raise error
except Exception as err:
if not scratch_org:
raise err
Expand All @@ -81,7 +98,7 @@ def delete_org_on_error(scratch_org=None, originating_user_id=None):
else:
error_msg = _(f"Are you certain that the Org still exists? {err.args[0]}")

error = ScratchOrgError(error_msg)
error = ScratchOrgError(error_msg, True)
scratch_org.remove_scratch_org(error, originating_user_id=originating_user_id)
raise error

Expand Down Expand Up @@ -239,7 +256,7 @@ def poll_for_scratch_org_completion(devhub_api, org_result):

if org_result["Status"] != "Active":
error = org_result["ErrorCode"] or _("Org creation timed out")
raise ScratchOrgError(f"Scratch org creation failed: {error}")
raise ScratchOrgError(f"Scratch org creation failed: {error}", False)

return org_result

Expand Down
30 changes: 21 additions & 9 deletions src/js/store/orgs/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ export const provisionFailed =
model,
message,
originating_user_id,
has_build_log,
}: {
model: Org | MinimalOrg;
message?: string;
originating_user_id: string | null;
has_build_log?: boolean;
}): ThunkResult<OrgProvisionFailed> =>
(dispatch, getState) => {
const state = getState();
Expand All @@ -183,21 +185,31 @@ export const provisionFailed =
);
}

const detailMsg = t(
'The last line of the log is “{{message}}” If you need support, your scratch org id is {{orgId}}.',
{
message,
orgId: model.id,
},
);
const detailMsg = has_build_log
? t(
'The last line of the log is “{{message}}” If you need support, your scratch org id is {{orgId}}.',
{
message,
orgId: model.id,
},
)
: t(
'{{message}}. If you need support, your scratch org id is {{orgId}}.',
{
message,
orgId: model.id,
},
);

dispatch(
addToast({
heading: msg,
details: detailMsg,
variant: 'error',
linkUrl: window.api_urls.scratch_org_log(model.id),
linkText: t('Download build log.'),
linkUrl: has_build_log
? window.api_urls.scratch_org_log(model.id)
: undefined,
linkText: has_build_log ? t('Download build log.') : undefined,
linkDownload: true,
linkDownloadFilename: t('Metecho Org {{orgId}} Build Log.txt', {
message,
Expand Down