Skip to content

Commit

Permalink
Add support for Timeline events (#366)
Browse files Browse the repository at this point in the history
This is primarily based on the timeline API response schema (using code generated from the schema by the script in `tool/process_github_schema.dart`). Where I could find existing model classes compatible with bits of that schema I tried to re-use them, extending them as necessary. I took some liberties where the GitHub API documentation was vague, contradictory, or otherwise dubious.

The comments on the new code are based on the comments in the response schema. They're not super helpful, if I'm honest.

I found that some of the model classes were inconsistent in various ways and tried to clean up the code near what I touched to be more consistent. For example, I made a bunch of fields on a bunch of model classes mutable where previously they were `final`, to be more consistent with other model classes. I also moved some constructors to be above their corresponding fields to be more consistent with other code that already did that.
  • Loading branch information
Hixie authored Apr 17, 2023
1 parent 043e0ed commit a308168
Show file tree
Hide file tree
Showing 23 changed files with 4,264 additions and 217 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 9.12.0

* Add support for issue and PR timeline events via `Issue.listTimeline`.

## 9.11.0

* expose IssueLabel.description; update labels REST APIs by @devoncarew in https://github.com/SpinlockLabs/github.dart/pull/355
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ GitHub.dart is committed to efficiency as much as possible. If your code is not

Pull Request rejections are not a bad thing. It just means you need to fix something. Perhaps it is important to define 'rejection' as it is used in this case. A rejection is when a GitHub.dart committer comments on a Pull Request with a comment like 'rejected due to incorrect formatting'.

## Generated code

To regenerate the JSON logic for the models, run:

```
dart run build_runner build -d
```

## Tests

To run the complete test suite you will need to install
Expand Down
2 changes: 2 additions & 0 deletions lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export 'package:github/src/common/model/repos_releases.dart';
export 'package:github/src/common/model/repos_stats.dart';
export 'package:github/src/common/model/repos_statuses.dart';
export 'package:github/src/common/model/search.dart';
export 'package:github/src/common/model/timeline.dart';
export 'package:github/src/common/model/timeline_support.dart';
export 'package:github/src/common/model/users.dart';
export 'package:github/src/common/orgs_service.dart';
export 'package:github/src/common/pulls_service.dart';
Expand Down
11 changes: 11 additions & 0 deletions lib/src/common/issues_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -432,4 +432,15 @@ class IssuesService extends Service {
.request('DELETE', '/repos/${slug.fullName}/milestones/$number')
.then((response) => response.statusCode == StatusCodes.NO_CONTENT);
}

/// Lists all timeline events for an issue.
///
/// API docs: https://docs.github.com/en/rest/issues/timeline?apiVersion=2022-11-28
Stream<TimelineEvent> listTimeline(RepositorySlug slug, int issueNumber) {
return PaginationHelper(github).objects(
'GET',
'/repos/${slug.fullName}/issues/$issueNumber/timeline',
TimelineEvent.fromJson,
);
}
}
82 changes: 81 additions & 1 deletion lib/src/common/model/issues.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:github/src/common.dart';
import 'package:github/src/common/model/users.dart';
import 'package:json_annotation/json_annotation.dart';

part 'issues.g.dart';
Expand All @@ -26,6 +25,24 @@ class Issue {
this.updatedAt,
this.body = '',
this.closedBy,

// Properties from the Timeline API
this.activeLockReason,
this.authorAssociation,
this.bodyHtml,
this.bodyText,
this.commentsUrl,
this.draft,
this.eventsUrl,
this.labelsUrl,
this.locked,
this.nodeId,
this.performedViaGithubApp,
this.reactions,
this.repository,
this.repositoryUrl,
this.stateReason,
this.timelineUrl,
}) {
if (labels != null) {
this.labels = labels;
Expand Down Expand Up @@ -89,6 +106,46 @@ class Issue {
bool get isOpen => state == 'open';
bool get isClosed => state == 'closed';

// The following properties were added to support the Timeline API.

String? activeLockReason;

/// How the author is associated with the repository.
///
/// Example: `OWNER`
String? authorAssociation;

String? bodyHtml;

String? bodyText;

String? commentsUrl;

bool? draft;

String? eventsUrl;

String? labelsUrl;

bool? locked;

String? nodeId;

GitHubApp? performedViaGithubApp;

ReactionRollup? reactions;

Repository? repository;

String? repositoryUrl;

/// The reason for the current state
///
/// Example: `not_planned`
String? stateReason;

String? timelineUrl;

factory Issue.fromJson(Map<String, dynamic> input) => _$IssueFromJson(input);
Map<String, dynamic> toJson() => _$IssueToJson(this);
}
Expand Down Expand Up @@ -204,6 +261,13 @@ class Milestone {
this.createdAt,
this.updatedAt,
this.dueOn,

// Properties from the Timeline API
this.closedAt,
this.htmlUrl,
this.labelsUrl,
this.nodeId,
this.url,
});

/// Unique Identifier for Milestone
Expand Down Expand Up @@ -241,6 +305,22 @@ class Milestone {
/// The due date for this milestone
DateTime? dueOn;

// The following properties were added to support the Timeline API.

DateTime? closedAt;

/// Example: `https://github.com/octocat/Hello-World/milestones/v1.0`
String? htmlUrl;

/// Example: `https://api.github.com/repos/octocat/Hello-World/milestones/1/labels`
String? labelsUrl;

/// Example: `MDk6TWlsZXN0b25lMTAwMjYwNA==`
String? nodeId;

/// Example: `https://api.github.com/repos/octocat/Hello-World/milestones/1`
String? url;

factory Milestone.fromJson(Map<String, dynamic> input) =>
_$MilestoneFromJson(input);
Map<String, dynamic> toJson() => _$MilestoneToJson(this);
Expand Down
51 changes: 51 additions & 0 deletions lib/src/common/model/issues.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a308168

Please sign in to comment.