Coverage for src/software_citation_sync/github_action.py: 84%

49 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-06-27 17:58 +0000

1# SPDX-FileCopyrightText: 2026 Arcangelo Massari <github@a.arcangelomassari.com> 

2# 

3# SPDX-License-Identifier: ISC 

4 

5from __future__ import annotations 

6 

7import os 

8from datetime import datetime, timezone 

9from pathlib import Path 

10 

11from software_citation_sync.config import CitationConfig, ProjectMetadata 

12from software_citation_sync.discovery import discover_project_metadata, discover_version 

13from software_citation_sync.software_heritage import archive_origin 

14from software_citation_sync.sync import ( 

15 check, 

16 write_citation_metadata, 

17 write_readme, 

18) 

19 

20CITATION_PATH = Path("CITATION.cff") 

21README_PATH = Path("README.md") 

22ARCHIVE_TIMEOUT_SECONDS = 300 

23ARCHIVE_POLL_INTERVAL_SECONDS = 10 

24 

25 

26def main() -> None: 

27 root = Path.cwd() 

28 version = _discover_required_version(root) 

29 date_released = _current_date() 

30 origin_url = _current_repository_url() 

31 software_heritage_url = archive_origin( 

32 origin_url, 

33 timeout_seconds=ARCHIVE_TIMEOUT_SECONDS, 

34 poll_interval_seconds=ARCHIVE_POLL_INTERVAL_SECONDS, 

35 ) 

36 project_metadata = _discover_required_project_metadata(root) if not CITATION_PATH.exists() else None 

37 citation_config = CitationConfig( 

38 citation_path=CITATION_PATH, 

39 readme_path=README_PATH, 

40 version=version, 

41 date_released=date_released, 

42 software_heritage_url=software_heritage_url, 

43 ) 

44 

45 citation_changed = write_citation_metadata(citation_config, project_metadata) 

46 readme_changed = write_readme(citation_config) 

47 check_result = check(citation_config) 

48 for error in check_result.errors: 

49 print(error) 

50 if not check_result.ok: 

51 raise SystemExit(1) 

52 

53 _set_output("changed", str(citation_changed or readme_changed).lower()) 

54 

55 

56def _discover_required_version(root: Path) -> str: 

57 version = discover_version(root) 

58 if version is None: 

59 msg = "Software version not found in package.json or pyproject.toml" 

60 raise ValueError(msg) 

61 return version 

62 

63 

64def _discover_required_project_metadata(root: Path) -> ProjectMetadata: 

65 project_metadata = discover_project_metadata(root) 

66 if project_metadata is None: 

67 msg = "Project metadata not found in package.json or pyproject.toml" 

68 raise ValueError(msg) 

69 return project_metadata 

70 

71 

72def _current_date() -> str: 

73 return datetime.now(timezone.utc).date().isoformat() 

74 

75 

76def _current_repository_url() -> str: 

77 return f"{os.environ['GITHUB_SERVER_URL'].rstrip('/')}/{os.environ['GITHUB_REPOSITORY']}" 

78 

79 

80def _set_output(name: str, value: str) -> None: 

81 with Path(os.environ["GITHUB_OUTPUT"]).open("a", encoding="utf-8") as file: 

82 file.write(f"{name}={value}\n") 

83 

84 

85if __name__ == "__main__": 

86 main()