github-backup 0.65.1__tar.gz → 0.66.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. {github_backup-0.65.1 → github_backup-0.66.0}/CHANGES.rst +124 -1
  2. {github_backup-0.65.1/github_backup.egg-info → github_backup-0.66.0}/PKG-INFO +3 -1
  3. {github_backup-0.65.1 → github_backup-0.66.0}/README +2 -0
  4. {github_backup-0.65.1 → github_backup-0.66.0}/README.rst +2 -0
  5. github_backup-0.66.0/github_backup/__init__.py +1 -0
  6. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup/github_backup.py +9 -0
  7. {github_backup-0.65.1 → github_backup-0.66.0/github_backup.egg-info}/PKG-INFO +3 -1
  8. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup.egg-info/SOURCES.txt +1 -0
  9. {github_backup-0.65.1 → github_backup-0.66.0}/release-requirements.txt +3 -3
  10. github_backup-0.66.0/tests/test_app_repositories.py +71 -0
  11. github_backup-0.65.1/github_backup/__init__.py +0 -1
  12. {github_backup-0.65.1 → github_backup-0.66.0}/LICENSE.txt +0 -0
  13. {github_backup-0.65.1 → github_backup-0.66.0}/MANIFEST.in +0 -0
  14. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup/__main__.py +0 -0
  15. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup/cli.py +0 -0
  16. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup/graphql_queries.py +0 -0
  17. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup.egg-info/dependency_links.txt +0 -0
  18. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup.egg-info/entry_points.txt +0 -0
  19. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup.egg-info/top_level.txt +0 -0
  20. {github_backup-0.65.1 → github_backup-0.66.0}/github_backup.egg-info/zip-safe +0 -0
  21. {github_backup-0.65.1 → github_backup-0.66.0}/requirements.txt +0 -0
  22. {github_backup-0.65.1 → github_backup-0.66.0}/setup.cfg +0 -0
  23. {github_backup-0.65.1 → github_backup-0.66.0}/setup.py +0 -0
  24. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_all_starred.py +0 -0
  25. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_attachments.py +0 -0
  26. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_auth.py +0 -0
  27. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_case_sensitivity.py +0 -0
  28. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_disabled_issues_pulls.py +0 -0
  29. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_discussions.py +0 -0
  30. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_gists.py +0 -0
  31. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_http_451.py +0 -0
  32. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_incremental_per_repository.py +0 -0
  33. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_issue_timeline.py +0 -0
  34. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_json_dump_if_changed.py +0 -0
  35. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_logging_subprocess.py +0 -0
  36. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_pagination.py +0 -0
  37. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_pull_incremental_pagination.py +0 -0
  38. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_pull_reviews.py +0 -0
  39. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_releases.py +0 -0
  40. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_retrieve_data.py +0 -0
  41. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_skip_assets_on.py +0 -0
  42. {github_backup-0.65.1 → github_backup-0.66.0}/tests/test_starred_skip_size_over.py +0 -0
@@ -1,9 +1,132 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- 0.65.1 (2026-08-01)
4
+ 0.66.0 (2026-10-28)
5
5
  -------------------
6
6
  ------------------------
7
+ - List a user's private repositories when authenticated as a GitHub App.
8
+ [AC Capehart, Claude Opus 5.5]
9
+
10
+ With --as-app there is no authenticated user, so a user-account backup
11
+ fell through to /users/{user}/repos, which only returns public
12
+ repositories. --private silently backed up nothing private.
13
+
14
+ An installation token can list everything the installation can access
15
+ via /installation/repositories, private repositories included. Org
16
+ backups keep using /orgs/{org}/repos, and -R still fetches the single
17
+ repository directly.
18
+ - Chore(deps): bump setuptools. [dependabot[bot]]
19
+
20
+ Bumps the python-packages group with 1 update: [setuptools](https://github.com/pypa/setuptools).
21
+
22
+
23
+ Updates `setuptools` from 84.2.0 to 84.2.1
24
+ - [Release notes](https://github.com/pypa/setuptools/releases)
25
+ - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
26
+ - [Commits](https://github.com/pypa/setuptools/compare/v84.2.0...v84.2.1)
27
+
28
+ ---
29
+ updated-dependencies:
30
+ - dependency-name: setuptools
31
+ dependency-version: 84.2.1
32
+ dependency-type: direct:production
33
+ update-type: version-update:semver-patch
34
+ dependency-group: python-packages
35
+ ...
36
+ - Chore(deps): bump setuptools. [dependabot[bot]]
37
+
38
+ Bumps the python-packages group with 1 update: [setuptools](https://github.com/pypa/setuptools).
39
+
40
+
41
+ Updates `setuptools` from 84.0.0 to 84.2.0
42
+ - [Release notes](https://github.com/pypa/setuptools/releases)
43
+ - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
44
+ - [Commits](https://github.com/pypa/setuptools/compare/v84.0.0...v84.2.0)
45
+
46
+ ---
47
+ updated-dependencies:
48
+ - dependency-name: setuptools
49
+ dependency-version: 84.2.0
50
+ dependency-type: direct:production
51
+ update-type: version-update:semver-minor
52
+ dependency-group: python-packages
53
+ ...
54
+ - Chore(deps): bump black. [dependabot[bot]]
55
+
56
+ Bumps the python-packages group with 1 update: [black](https://github.com/psf/black).
57
+
58
+
59
+ Updates `black` from 26.10.0 to 26.10.1
60
+ - [Release notes](https://github.com/psf/black/releases)
61
+ - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
62
+ - [Commits](https://github.com/psf/black/compare/26.10.0...26.10.1)
63
+
64
+ ---
65
+ updated-dependencies:
66
+ - dependency-name: black
67
+ dependency-version: 26.10.1
68
+ dependency-type: direct:production
69
+ update-type: version-update:semver-patch
70
+ dependency-group: python-packages
71
+ ...
72
+ - Chore(deps): bump black. [dependabot[bot]]
73
+
74
+ Bumps the python-packages group with 1 update: [black](https://github.com/psf/black).
75
+
76
+
77
+ Updates `black` from 26.5.1 to 26.10.0
78
+ - [Release notes](https://github.com/psf/black/releases)
79
+ - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
80
+ - [Commits](https://github.com/psf/black/compare/26.5.1...26.10.0)
81
+
82
+ ---
83
+ updated-dependencies:
84
+ - dependency-name: black
85
+ dependency-version: 26.10.0
86
+ dependency-type: direct:production
87
+ update-type: version-update:semver-minor
88
+ dependency-group: python-packages
89
+ ...
90
+ - Chore(deps): bump flake8 in the python-packages group.
91
+ [dependabot[bot]]
92
+
93
+ Bumps the python-packages group with 1 update: [flake8](https://github.com/pycqa/flake8).
94
+
95
+
96
+ Updates `flake8` from 7.3.0 to 7.4.1
97
+ - [Commits](https://github.com/pycqa/flake8/compare/7.3.0...7.4.1)
98
+
99
+ ---
100
+ updated-dependencies:
101
+ - dependency-name: flake8
102
+ dependency-version: 7.4.1
103
+ dependency-type: direct:production
104
+ update-type: version-update:semver-minor
105
+ dependency-group: python-packages
106
+ ...
107
+ - Chore(deps): bump setuptools in the python-packages group.
108
+ [dependabot[bot]]
109
+
110
+ Bumps the python-packages group with 1 update: [setuptools](https://github.com/pypa/setuptools).
111
+
112
+
113
+ Updates `setuptools` from 83.0.0 to 84.0.0
114
+ - [Release notes](https://github.com/pypa/setuptools/releases)
115
+ - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
116
+ - [Commits](https://github.com/pypa/setuptools/compare/v83.0.0...v84.0.0)
117
+
118
+ ---
119
+ updated-dependencies:
120
+ - dependency-name: setuptools
121
+ dependency-version: 84.0.0
122
+ dependency-type: direct:production
123
+ update-type: version-update:semver-major
124
+ dependency-group: python-packages
125
+ ...
126
+
127
+
128
+ 0.65.1 (2026-08-01)
129
+ -------------------
7
130
  - Fix timeline not being properly incremental. [Duncan Ogilvie]
8
131
  - Chore(deps): bump twine from 6.2.0 to 7.0.0 in the python-packages
9
132
  group. [dependabot[bot]]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-backup
3
- Version: 0.65.1
3
+ Version: 0.66.0
4
4
  Summary: backup a github user or organization
5
5
  Home-page: http://github.com/josegonzalez/python-github-backup
6
6
  Author: Jose Diaz-Gonzalez
@@ -229,6 +229,8 @@ GitHub Apps
229
229
 
230
230
  GitHub Apps are ideal for organization backups in CI/CD. Tokens are scoped to specific repositories and expire after 1 hour.
231
231
 
232
+ For a user account (no ``--organization``), ``--as-app`` lists the repositories the installation can access, so private repositories are included.
233
+
232
234
  **One-time setup:**
233
235
 
234
236
  1. Create a GitHub App at *Settings -> Developer Settings -> GitHub Apps -> New GitHub App*
@@ -199,6 +199,8 @@ GitHub Apps
199
199
 
200
200
  GitHub Apps are ideal for organization backups in CI/CD. Tokens are scoped to specific repositories and expire after 1 hour.
201
201
 
202
+ For a user account (no ``--organization``), ``--as-app`` lists the repositories the installation can access, so private repositories are included.
203
+
202
204
  **One-time setup:**
203
205
 
204
206
  1. Create a GitHub App at *Settings -> Developer Settings -> GitHub Apps -> New GitHub App*
@@ -199,6 +199,8 @@ GitHub Apps
199
199
 
200
200
  GitHub Apps are ideal for organization backups in CI/CD. Tokens are scoped to specific repositories and expire after 1 hour.
201
201
 
202
+ For a user account (no ``--organization``), ``--as-app`` lists the repositories the installation can access, so private repositories are included.
203
+
202
204
  **One-time setup:**
203
205
 
204
206
  1. Create a GitHub App at *Settings -> Developer Settings -> GitHub Apps -> New GitHub App*
@@ -0,0 +1 @@
1
+ __version__ = "0.66.0"
@@ -1838,6 +1838,11 @@ def retrieve_repositories(args, authenticated_user):
1838
1838
  if args.user == authenticated_user["login"]:
1839
1839
  # we must use the /user/repos API to be able to access private repos
1840
1840
  template = "https://{0}/user/repos".format(get_github_api_host(args))
1841
+ elif args.as_app and not args.organization:
1842
+ # /users/{user}/repos is public-only; the installation sees private repos too
1843
+ template = "https://{0}/installation/repositories".format(
1844
+ get_github_api_host(args)
1845
+ )
1841
1846
  else:
1842
1847
  if args.private and not args.organization:
1843
1848
  logger.warning(
@@ -1868,6 +1873,10 @@ def retrieve_repositories(args, authenticated_user):
1868
1873
  logger.warning(f"Legal notice: {e.legal_url}")
1869
1874
  return []
1870
1875
 
1876
+ if template.endswith("/installation/repositories"):
1877
+ # Each page is {"total_count": ..., "repositories": [...]}
1878
+ repos = [repo for page in repos for repo in page["repositories"]]
1879
+
1871
1880
  return retrieve_additional_repositories(args, authenticated_user, repos)
1872
1881
 
1873
1882
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-backup
3
- Version: 0.65.1
3
+ Version: 0.66.0
4
4
  Summary: backup a github user or organization
5
5
  Home-page: http://github.com/josegonzalez/python-github-backup
6
6
  Author: Jose Diaz-Gonzalez
@@ -229,6 +229,8 @@ GitHub Apps
229
229
 
230
230
  GitHub Apps are ideal for organization backups in CI/CD. Tokens are scoped to specific repositories and expire after 1 hour.
231
231
 
232
+ For a user account (no ``--organization``), ``--as-app`` lists the repositories the installation can access, so private repositories are included.
233
+
232
234
  **One-time setup:**
233
235
 
234
236
  1. Create a GitHub App at *Settings -> Developer Settings -> GitHub Apps -> New GitHub App*
@@ -18,6 +18,7 @@ github_backup.egg-info/entry_points.txt
18
18
  github_backup.egg-info/top_level.txt
19
19
  github_backup.egg-info/zip-safe
20
20
  tests/test_all_starred.py
21
+ tests/test_app_repositories.py
21
22
  tests/test_attachments.py
22
23
  tests/test_auth.py
23
24
  tests/test_case_sensitivity.py
@@ -1,7 +1,7 @@
1
1
  # Linting & Formatting
2
2
  autopep8==2.3.2
3
- black==26.5.1
4
- flake8==7.3.0
3
+ black==26.10.1
4
+ flake8==7.4.1
5
5
 
6
6
  # Testing
7
7
  pytest==9.1.1
@@ -9,7 +9,7 @@ pytest==9.1.1
9
9
  # Release & Publishing
10
10
  twine==7.0.0
11
11
  gitchangelog==3.0.4
12
- setuptools==83.0.0
12
+ setuptools==84.2.1
13
13
 
14
14
  # Documentation
15
15
  restructuredtext-lint==2.0.2
@@ -0,0 +1,71 @@
1
+ """Tests for listing a user's repositories with a GitHub App installation token."""
2
+
3
+ from unittest.mock import patch
4
+
5
+ import pytest
6
+
7
+ from github_backup import github_backup
8
+
9
+ NO_USER = {"login": None}
10
+
11
+
12
+ def page(*names):
13
+ return {
14
+ "total_count": 3,
15
+ "repositories": [{"name": name, "private": True} for name in names],
16
+ }
17
+
18
+
19
+ @pytest.fixture
20
+ def mock_retrieve_data():
21
+ with patch("github_backup.github_backup.retrieve_data") as mock:
22
+ yield mock
23
+
24
+
25
+ def test_app_lists_user_repositories_from_installation(create_args, mock_retrieve_data):
26
+ args = create_args(as_app=True, include_repository=True)
27
+ mock_retrieve_data.return_value = [page("a", "b"), page("c")]
28
+
29
+ repos = github_backup.retrieve_repositories(args, NO_USER)
30
+
31
+ assert mock_retrieve_data.call_args.args[1] == (
32
+ "https://api.github.com/installation/repositories"
33
+ )
34
+ assert [r["name"] for r in repos] == ["a", "b", "c"]
35
+
36
+
37
+ def test_app_installation_listing_uses_ghes_host(create_args, mock_retrieve_data):
38
+ args = create_args(
39
+ as_app=True, include_repository=True, github_host="ghe.example.com"
40
+ )
41
+ mock_retrieve_data.return_value = [page("a")]
42
+
43
+ github_backup.retrieve_repositories(args, NO_USER)
44
+
45
+ assert mock_retrieve_data.call_args.args[1] == (
46
+ "https://ghe.example.com/api/v3/installation/repositories"
47
+ )
48
+
49
+
50
+ def test_app_organization_still_lists_org_repositories(create_args, mock_retrieve_data):
51
+ args = create_args(as_app=True, include_repository=True, organization=True)
52
+ mock_retrieve_data.return_value = [{"name": "a"}]
53
+
54
+ repos = github_backup.retrieve_repositories(args, NO_USER)
55
+
56
+ assert mock_retrieve_data.call_args.args[1] == (
57
+ "https://api.github.com/orgs/testuser/repos"
58
+ )
59
+ assert repos == [{"name": "a"}]
60
+
61
+
62
+ def test_app_single_repository_is_fetched_directly(create_args, mock_retrieve_data):
63
+ args = create_args(as_app=True, repository="dotfiles")
64
+ mock_retrieve_data.return_value = [{"name": "dotfiles"}]
65
+
66
+ repos = github_backup.retrieve_repositories(args, NO_USER)
67
+
68
+ assert mock_retrieve_data.call_args.args[1] == (
69
+ "https://api.github.com/repos/testuser/dotfiles"
70
+ )
71
+ assert repos == [{"name": "dotfiles"}]
@@ -1 +0,0 @@
1
- __version__ = "0.65.1"
File without changes
File without changes