diff --git a/CHANGELOG.md b/CHANGELOG.md index 8027a432..6193c995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 9.18.0 + +* Adds the initial `PushEvent` object in https://github.com/SpinlockLabs/github.dart/pull/386 +* Update the `Repository` values `created_at` and `pushed_at` to handle integer times + ## 9.17.0 * Add bearerToken constructor to Authentication class by @kevmoo in https://github.com/SpinlockLabs/github.dart/pull/381 @@ -307,7 +312,7 @@ Map? files; - Clean up lints https://github.com/SpinlockLabs/github.dart/pull/202 ## 6.0.5 - - Fix null errors issue https://github.com/SpinlockLabs/github.dart/issues/199 + - Fix null errors issue https://github.com/SpinlockLabs/github.dart/issues/199 ## 6.0.4 - This fixes #196 (https://github.com/SpinlockLabs/github.dart/issues/196) @@ -357,10 +362,10 @@ Map? files; Deprecations: -- The `draft` and `prerelease` properties in the CreateRelease and Release +- The `draft` and `prerelease` properties in the CreateRelease and Release - classes have been renamed to `isDraft` and `isPrerelease` for clarity. -- Release.targetCommitsh has been renamed to Release.targetCommitish. -- The `release` parameter in RepositoriesService.createRelease +- Release.targetCommitsh has been renamed to Release.targetCommitish. +- The `release` parameter in RepositoriesService.createRelease has been renamed to `createRelease`. - `RepositoriesService.getRelease` has been renamed to `RepositoriesService.getReleaseById` @@ -369,7 +374,7 @@ has been renamed to `createRelease`. - Add access to labels on Pull Requests https://github.com/SpinlockLabs/github.dart/pull/163 - Adding draft property to PR model https://github.com/SpinlockLabs/github.dart/pull/162 - updateFile request must be a PUT https://github.com/SpinlockLabs/github.dart/pull/160 - + ## v5.1.0 - `Repository`: added `updatedAt` and `license` fields. @@ -386,7 +391,7 @@ has been renamed to `createRelease`. ## v5.0.0 -- **BREAKING** `RepositoriesService.listCollaborators` now returns +- **BREAKING** `RepositoriesService.listCollaborators` now returns `Stream` instead of `Stream`. - `Collaborator` is a new type that includes collaborator-specific information. @@ -403,7 +408,7 @@ has been renamed to `createRelease`. - Removed unsupported `limit` parameter. - Removed flaky retry logic. Instead, `NotReady` is thrown, which can be used to decide to retry at the call site. - - Made associated classes `ContributorStatistics` and + - Made associated classes `ContributorStatistics` and `ContributorWeekStatistics` immutable. Since these classes are only meant as return values, we're not treating this as a breaking change. - Added `Stream github.search.code(...)` search API @@ -433,7 +438,7 @@ has been renamed to `createRelease`. ## v2.3.2 -- Automatically attempt to find GitHub user information in the process environment when running on the standalone VM. +- Automatically attempt to find GitHub user information in the process environment when running on the standalone VM. - Add `ref` parameter to `getReadme` method for the repository service. ## v2.3.1 @@ -447,7 +452,7 @@ has been renamed to `createRelease`. - Moved `CHANGELOG` content back to repo. - Added `rateLimitLimit`, `rateLimitRemaining` and `rateLimitReset` to `GitHub`. - Added `id` to `Issue` -- Added `direction`, `sort` and `since` optional arguments to +- Added `direction`, `sort` and `since` optional arguments to `IssueService.listByRepo`. ## v2.1.0 diff --git a/lib/src/common/model/git.dart b/lib/src/common/model/git.dart index 136c01c4..0e655572 100644 --- a/lib/src/common/model/git.dart +++ b/lib/src/common/model/git.dart @@ -98,6 +98,28 @@ class CreateGitCommit { Map toJson() => _$CreateGitCommitToJson(this); } +/// Model class for a pushed commit. +@JsonSerializable() +class PushGitCommit { + PushGitCommit(this.id, this.message, this.timestamp, this.url); + + /// The commit hash. + String? id; + + /// The commit message. + String? message; + + /// The timestamp of the commit. + DateTime? timestamp; + + /// The direct url to the commit. + String? url; + + factory PushGitCommit.fromJson(Map input) => + _$PushGitCommitFromJson(input); + Map toJson() => _$PushGitCommitToJson(this); +} + /// Model class for an author or committer of a commit. The [GitCommitUser] may /// not correspond to a GitHub [User]. @JsonSerializable(includeIfNull: false) diff --git a/lib/src/common/model/git.g.dart b/lib/src/common/model/git.g.dart index 61d5fc44..7b2ba940 100644 --- a/lib/src/common/model/git.g.dart +++ b/lib/src/common/model/git.g.dart @@ -88,6 +88,24 @@ Map _$CreateGitCommitToJson(CreateGitCommit instance) => 'author': instance.author, }; +PushGitCommit _$PushGitCommitFromJson(Map json) => + PushGitCommit( + json['id'] as String?, + json['message'] as String?, + json['timestamp'] == null + ? null + : DateTime.parse(json['timestamp'] as String), + json['url'] as String?, + ); + +Map _$PushGitCommitToJson(PushGitCommit instance) => + { + 'id': instance.id, + 'message': instance.message, + 'timestamp': instance.timestamp?.toIso8601String(), + 'url': instance.url, + }; + GitCommitUser _$GitCommitUserFromJson(Map json) => GitCommitUser( json['name'] as String?, diff --git a/lib/src/common/model/repos.dart b/lib/src/common/model/repos.dart index d09c1a7e..4e46566d 100644 --- a/lib/src/common/model/repos.dart +++ b/lib/src/common/model/repos.dart @@ -225,9 +225,11 @@ class Repository { int networkCount; /// The time the repository was created at + @JsonKey(fromJson: Repository.dynamicToDateTime) DateTime? createdAt; /// The last time the repository was pushed at + @JsonKey(fromJson: Repository.dynamicToDateTime) DateTime? pushedAt; DateTime? updatedAt; @@ -459,6 +461,18 @@ class Repository { @override String toString() => 'Repository: $owner/$name'; + + /// In some cases, github webhooks send time values as an integer. This method + /// is added to handle those cases, but otherwise parse like normal. + static DateTime? dynamicToDateTime(dynamic time) { + if (time == null) { + return null; + } + if (time.runtimeType == int) { + return DateTime.fromMillisecondsSinceEpoch(time * 1000); + } + return DateTime.parse(time as String); + } } /// Model class for repository permissions. diff --git a/lib/src/common/model/repos.g.dart b/lib/src/common/model/repos.g.dart index 490b18b1..871a3284 100644 --- a/lib/src/common/model/repos.g.dart +++ b/lib/src/common/model/repos.g.dart @@ -46,9 +46,7 @@ Repository _$RepositoryFromJson(Map json) => Repository( sshUrl: json['ssh_url'] as String? ?? '', svnUrl: json['svn_url'] as String? ?? '', defaultBranch: json['default_branch'] as String? ?? '', - createdAt: json['created_at'] == null - ? null - : DateTime.parse(json['created_at'] as String), + createdAt: Repository.dynamicToDateTime(json['created_at']), isPrivate: json['private'] as bool? ?? false, isFork: json['fork'] as bool? ?? false, stargazersCount: json['stargazers_count'] as int? ?? 0, @@ -68,9 +66,7 @@ Repository _$RepositoryFromJson(Map json) => Repository( updatedAt: json['updated_at'] == null ? null : DateTime.parse(json['updated_at'] as String), - pushedAt: json['pushed_at'] == null - ? null - : DateTime.parse(json['pushed_at'] as String), + pushedAt: Repository.dynamicToDateTime(json['pushed_at']), license: json['license'] == null ? null : LicenseKind.fromJson(json['license'] as Map), diff --git a/lib/src/server/hooks.dart b/lib/src/server/hooks.dart index ea250c48..3f8987d2 100644 --- a/lib/src/server/hooks.dart +++ b/lib/src/server/hooks.dart @@ -235,3 +235,40 @@ class CreateEvent extends HookEvent { Map toJson() => _$CreateEventToJson(this); } + +@JsonSerializable(fieldRename: FieldRename.snake) +class PushEvent extends HookEvent { + PushEvent({ + this.ref, + this.before, + this.after, + this.repository, + this.headCommit, + this.commits, + this.sender, + }); + + factory PushEvent.fromJson(Map input) => + _$PushEventFromJson(input); + String? ref; + String? before; + String? after; + @JsonKey(toJson: handleIntegerTimes) + Repository? repository; + PushGitCommit? headCommit; + List? commits; + User? sender; + + Map toJson() => _$PushEventToJson(this); + + static Map? handleIntegerTimes(Repository? repository) { + var repositoryMap = repository?.toJson(); + for (final parameter in ['created_at', 'pushed_at']) { + if (repositoryMap?[parameter] != null) { + final createdAt = DateTime.parse(repositoryMap?[parameter]); + repositoryMap?[parameter] = createdAt.millisecondsSinceEpoch ~/ 1000; + } + } + return repositoryMap; + } +} diff --git a/lib/src/server/hooks.g.dart b/lib/src/server/hooks.g.dart index 3babd5cf..0e4ca02e 100644 --- a/lib/src/server/hooks.g.dart +++ b/lib/src/server/hooks.g.dart @@ -173,3 +173,31 @@ Map _$CreateEventToJson(CreateEvent instance) => 'repository': instance.repository, 'sender': instance.sender, }; + +PushEvent _$PushEventFromJson(Map json) => PushEvent( + ref: json['ref'] as String?, + before: json['before'] as String?, + after: json['after'] as String?, + repository: json['repository'] == null + ? null + : Repository.fromJson(json['repository'] as Map), + headCommit: json['head_commit'] == null + ? null + : PushGitCommit.fromJson(json['head_commit'] as Map), + commits: (json['commits'] as List?) + ?.map((e) => PushGitCommit.fromJson(e as Map)) + .toList(), + sender: json['sender'] == null + ? null + : User.fromJson(json['sender'] as Map), + ); + +Map _$PushEventToJson(PushEvent instance) => { + 'ref': instance.ref, + 'before': instance.before, + 'after': instance.after, + 'repository': PushEvent.handleIntegerTimes(instance.repository), + 'head_commit': instance.headCommit, + 'commits': instance.commits, + 'sender': instance.sender, + }; diff --git a/pubspec.yaml b/pubspec.yaml index 0a917ea4..9de50e38 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: github -version: 9.17.0 +version: 9.18.0 description: A high-level GitHub API Client Library that uses Github's v3 API homepage: https://github.com/SpinlockLabs/github.dart diff --git a/test/data_object_test.dart b/test/data_object_test.dart index f1d1d5db..1654b0a6 100644 --- a/test/data_object_test.dart +++ b/test/data_object_test.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:github/github.dart'; +import 'package:github/hooks.dart'; import 'package:test/test.dart'; const _licenseJson = r''' { @@ -29,6 +30,134 @@ const _licenseJson = r''' { } }'''; +const _pushEventJson = r'''{ + "ref": "refs/heads/main", + "before": "def456def456", + "after": "abc123abc123", + "base_ref": null, + "repository": { + "name": "fake-repository", + "id": 680238321, + "full_name": "fakeuser/fake-repository", + "owner": { + "login": "fakeuser", + "id": 102626803, + "avatar_url": "https://avatars.githubusercontent.com/u/102626803?v=4", + "html_url": "https://github.com/fakeuser" + }, + "private": false, + "fork": false, + "html_url": "https://github.com/fakeuser/fake-repository", + "description": "", + "clone_url": "https://github.com/fakeuser/fake-repository.git", + "ssh_url": "git@github.com:fakeuser/fake-repository.git", + "svn_url": "https://github.com/fakeuser/fake-repository", + "git_url": "git://github.com/fakeuser/fake-repository.git", + "homepage": "", + "size": 1, + "stargazers_count": 0, + "watchers_count": 0, + "language": "", + "has_issues": true, + "has_wiki": true, + "has_downloads": true, + "has_pages": false, + "forks_count": 0, + "open_issues_count": 0, + "default_branch": "main", + "subscribers_count": 0, + "network_count": 0, + "created_at": 1692379465, + "pushed_at": 1694031233, + "updated_at": "2023-08-18T17:24:25.000Z", + "archived": false, + "disabled": false, + "allow_forking": true, + "assignees_url": "https://api.github.com/repos/fakeuser/fake-repository/assignees{/user}", + "blobs_url": "https://api.github.com/repos/fakeuser/fake-repository/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/fakeuser/fake-repository/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/fakeuser/fake-repository/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/fakeuser/fake-repository/comments{/number}", + "commits_url": "https://api.github.com/repos/fakeuser/fake-repository/commits{/sha}", + "compare_url": "https://api.github.com/repos/fakeuser/fake-repository/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/fakeuser/fake-repository/contents/{+path}", + "contributors_url": "https://api.github.com/repos/fakeuser/fake-repository/contributors", + "deployments_url": "https://api.github.com/repos/fakeuser/fake-repository/deployments", + "downloads_url": "https://api.github.com/repos/fakeuser/fake-repository/downloads", + "events_url": "https://api.github.com/repos/fakeuser/fake-repository/events", + "forks": 0, + "forks_url": "https://api.github.com/repos/fakeuser/fake-repository/forks", + "git_commits_url": "https://api.github.com/repos/fakeuser/fake-repository/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/fakeuser/fake-repository/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/fakeuser/fake-repository/git/tags{/sha}", + "has_discussions": false, + "has_projects": true, + "hooks_url": "https://api.github.com/repos/fakeuser/fake-repository/hooks", + "is_template": false, + "issue_comment_url": "https://api.github.com/repos/fakeuser/fake-repository/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/fakeuser/fake-repository/issues/events{/number}", + "issues_url": "https://api.github.com/repos/fakeuser/fake-repository/issues{/number}", + "keys_url": "https://api.github.com/repos/fakeuser/fake-repository/keys{/key_id}", + "labels_url": "https://api.github.com/repos/fakeuser/fake-repository/labels{/name}", + "languages_url": "https://api.github.com/repos/fakeuser/fake-repository/languages", + "master_branch": "main", + "merges_url": "https://api.github.com/repos/fakeuser/fake-repository/merges", + "milestones_url": "https://api.github.com/repos/fakeuser/fake-repository/milestones{/number}", + "node_id": "R_kgDOKIuc8Q", + "notifications_url": "https://api.github.com/repos/fakeuser/fake-repository/notifications{?since,all,participating}", + "open_issues": 0, + "pulls_url": "https://api.github.com/repos/fakeuser/fake-repository/pulls{/number}", + "releases_url": "https://api.github.com/repos/fakeuser/fake-repository/releases{/id}", + "stargazers_url": "https://api.github.com/repos/fakeuser/fake-repository/stargazers", + "statuses_url": "https://api.github.com/repos/fakeuser/fake-repository/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/fakeuser/fake-repository/subscribers", + "subscription_url": "https://api.github.com/repos/fakeuser/fake-repository/subscription", + "tags_url": "https://api.github.com/repos/fakeuser/fake-repository/tags", + "teams_url": "https://api.github.com/repos/fakeuser/fake-repository/teams", + "topics": [], + "trees_url": "https://api.github.com/repos/fakeuser/fake-repository/git/trees{/sha}", + "url": "https://github.com/fakeuser/fake-repository", + "visibility": "public", + "watchers": 0, + "web_commit_signoff_required": false + }, + "head_commit": { + "id": "f1eab4d20a72fe5495183136e36584dfab447faf", + "message": "A message", + "timestamp": "2023-09-06T15:14:10.000Z", + "url": "fake-github-url.com" + }, + "commits": [ + { + "id": "f1eab4d20a72fe5495183136e36584dfab447faf", + "message": "A message", + "timestamp": "2023-09-06T15:14:10.000Z", + "url": "fake-github-url.com" + } + ], + "sender": { + "login": "fakeuser", + "id": 102626803, + "avatar_url": "https://avatars.githubusercontent.com/u/102626803?v=4", + "html_url": "https://github.com/fakeuser", + "site_admin": false, + "events_url": "https://api.github.com/users/fakeuser/events{/privacy}", + "followers_url": "https://api.github.com/users/fakeuser/followers", + "following_url": "https://api.github.com/users/fakeuser/following{/other_user}", + "gists_url": "https://api.github.com/users/fakeuser/gists{/gist_id}", + "gravatar_id": "", + "node_id": "U_kgDOBh318w", + "organizations_url": "https://api.github.com/users/fakeuser/orgs", + "received_events_url": "https://api.github.com/users/fakeuser/received_events", + "repos_url": "https://api.github.com/users/fakeuser/repos", + "starred_url": "https://api.github.com/users/fakeuser/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/fakeuser/subscriptions", + "type": "User", + "url": "https://api.github.com/users/fakeuser" + } +} +'''; + void main() { test('License round-trip', () { final licenseJson = jsonDecode(_licenseJson) as Map; @@ -39,6 +168,16 @@ void main() { expect(_prettyEncode(toJson), _prettyEncode(licenseJson)); }); + + test('PushEvent round-trip', () { + final pushEventJson = jsonDecode(_pushEventJson) as Map; + + final instance = PushEvent.fromJson(pushEventJson); + + final toJson = instance.toJson(); + + expect(_prettyEncode(toJson), _prettyEncode(pushEventJson)); + }); } String _prettyEncode(obj) => GitHubJson.encode(obj, indent: ' '); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy