Skip to content
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
10 changes: 9 additions & 1 deletion cloudpebble/ide/api/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ def set_project_repo(request, project_id):
# Generate a new hook UUID
project.github_hook_uuid = uuid.uuid4().hex
# Set it up
g_repo.create_hook('web', {'url': settings.GITHUB_HOOK_TEMPLATE % {'project': project.id, 'key': project.github_hook_uuid}, 'content_type': 'form'}, ['push'], True)
try:
g_repo.create_hook('web', {'url': settings.GITHUB_HOOK_TEMPLATE % {'project': project.id, 'key': project.github_hook_uuid}, 'content_type': 'form'}, ['push'], True)
except GithubException:
# The user lacks admin access to the repo (e.g. they imported a
# public repo with "use as git remote" but don't have push access,
# so check_repo_access was never called). Roll back the hook UUID
# and return a clean access-denied response instead of a 500.
project.github_hook_uuid = None
return {'exists': True, 'access': False, 'updated': False, 'branch_exists': True}
elif not auto_pull:
if project.github_hook_uuid is not None:
try:
Expand Down
2 changes: 1 addition & 1 deletion cloudpebble/ide/static/ide/js/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ CloudPebble.GitHub = (function() {
return;
}
if(!data.access) {
throw new Error(gettext("You don't have access to that repository."));
throw new Error(gettext("You do not have write access to that repository which is required to create a GitHub hook."));
}
}).catch(function(error) {
enable_all();
Expand Down
13 changes: 11 additions & 2 deletions cloudpebble/ide/tasks/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,14 @@ def do_github_pull(project_id, force=False):
if changed and project.github_hook_build:
build = BuildResult.objects.create(project=project)
publish_event(project_id, 'build_start', build_id=build.id)
run_compile(build.id)
# Run the build as a separate async task so this task returns as soon
# as the pull is complete. The frontend shows the "Pulled successfully"
# alert and unlocks controls on the pull_complete SSE event (already
# published above); build progress is reported independently via the
# build_start/build_complete SSE events. Calling run_compile
# synchronously here would block this task until the build finished,
# delaying the pull_complete UI feedback by the entire build duration.
run_compile.delay(build.id)

return changed

Expand All @@ -920,7 +927,9 @@ def hooked_commit(project_id, target_commit):
if project.github_hook_build:
build = BuildResult.objects.create(project=project)
publish_event(project_id, 'build_start', build_id=build.id)
run_compile(build.id)
# Run the build asynchronously so this task returns immediately after
# the pull completes. See do_github_pull for the rationale.
run_compile.delay(build.id)
did_something = True

return did_something
1 change: 0 additions & 1 deletion cloudpebble/ide/tests/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -1424,4 +1424,3 @@ def test_full_pull_stamps_sha_in_atomic_block(
mock_atomic.assert_called_once()
self.assertEqual(self.project.github_last_commit, 'newsha')
self.assertEqual(self.project.github_last_sync, '2025-01-01T00:00:00Z')
self.project.save.assert_called_once()
8 changes: 4 additions & 4 deletions cloudpebble/ide/tests/test_sse.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def test_skip_build_when_auto_build_disabled(self, mock_pull, mock_compile, mock
hooked_commit(project.id, 'newsha')
types = [call[0][1] for call in mock_publish.call_args_list]
self.assertNotIn('build_start', types)
mock_compile.assert_not_called()
mock_compile.delay.assert_not_called()


class TestDoGithubPullEvents(TestCase):
Expand Down Expand Up @@ -300,7 +300,7 @@ def test_auto_builds_when_hook_build_enabled(self, mock_pull, mock_compile, mock
do_github_pull(project.id)
types = [call[0][1] for call in mock_publish.call_args_list]
self.assertIn('build_start', types)
mock_compile.assert_called_once()
mock_compile.delay.assert_called_once()

@mock.patch('ide.tasks.git.publish_event')
@mock.patch('ide.tasks.git.run_compile')
Expand All @@ -317,7 +317,7 @@ def test_no_auto_build_when_hook_build_disabled(self, mock_pull, mock_compile, m
do_github_pull(project.id)
types = [call[0][1] for call in mock_publish.call_args_list]
self.assertNotIn('build_start', types)
mock_compile.assert_not_called()
mock_compile.delay.assert_not_called()

@mock.patch('ide.tasks.git.publish_event')
@mock.patch('ide.tasks.git.github_pull')
Expand Down Expand Up @@ -350,7 +350,7 @@ def test_no_auto_build_when_nothing_changed(self, mock_pull, mock_compile, mock_
do_github_pull(project.id)
types = [call[0][1] for call in mock_publish.call_args_list]
self.assertNotIn('build_start', types)
mock_compile.assert_not_called()
mock_compile.delay.assert_not_called()


class TestRunCompileEvents(TestCase):
Expand Down
Loading