Repository: netbox-community/netbox

Issue:
Datasources stuck in sync when using git + ssh from ./manage.py syncdatasource
### NetBox version

v3.6.1

### Python version

3.11

### Steps to Reproduce

In Data Sources
Add
Name: test
Type: git
URL: git@github.com:netbox-community/netbox.git
Create

docker compose exec netbox ./manage.py syncdatasource test





### Expected Behavior

Usually leads to some sort of ssh question or failure, and I would expect the exception to set the status to failed, and then be able to hit sync again.

I'm not sure exactly how NetBox works, but looking at one of the exceptions...
core.exceptions.SyncError: Fetching remote data failed (HangupException): 

class SyncError(Exception):
    pass

Does this mean the status is not being reset correctly due to the status being left as syncing?



### Observed Behavior

datasource.status = syncing in nbshell
'syncing' in gui
Sync option is now greyed out and cannot reset status without manually setting it in nbshell:

for d in DataSource.objects.filter(status='syncing'):
  d.status = 'failed'
  d.save()



Discussion:
This appears to be a bug in the `syncdatasource` management command specifically: Testing using the normal sync (via a background job) returns the status to failed as expected.
I originally started investigating this as I was getting this issue via the gui, I think that was version 3.6.0. When I did some more testing in my test environment I was only getting the issue via the syncdatasource command, so that all I included in the issue. So either the other issue was just fixed, or there are some other potential code paths in the gui that end up leaving it run sync. I had been working my way through a number of scenarios in my prod environment so not easy to say what the difference was 
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).

Resolving patch:
diff --git a/netbox/core/management/commands/syncdatasource.py b/netbox/core/management/commands/syncdatasource.py
--- a/netbox/core/management/commands/syncdatasource.py
+++ b/netbox/core/management/commands/syncdatasource.py
@@ -1,5 +1,6 @@
 from django.core.management.base import BaseCommand, CommandError
 
+from core.choices import DataSourceStatusChoices
 from core.models import DataSource
 
 
@@ -33,9 +34,13 @@ def handle(self, *args, **options):
         for i, datasource in enumerate(datasources, start=1):
             self.stdout.write(f"[{i}] Syncing {datasource}... ", ending='')
             self.stdout.flush()
-            datasource.sync()
-            self.stdout.write(datasource.get_status_display())
-            self.stdout.flush()
+            try:
+                datasource.sync()
+                self.stdout.write(datasource.get_status_display())
+                self.stdout.flush()
+            except Exception as e:
+                DataSource.objects.filter(pk=datasource.pk).update(status=DataSourceStatusChoices.FAILED)
+                raise e
 
         if len(options['name']) > 1:
             self.stdout.write(f"Finished.")


Test patch: