add commentary and (unused) check for token applicability

This commit is contained in:
Emil Lerch 2025-07-17 11:50:21 -07:00
parent 3b195a9eb6
commit f4d66203b9
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 90 additions and 4 deletions

View file

@ -24,10 +24,10 @@ zig build
2. Run the application:
```bash
./zig-out/bin/release-tracker config.json
./zig-out/bin/release-tracker config.json [output filename]
```
3. The RSS feed will be generated as `releases.xml`
3. The RSS feed will be generated as `releases.xml` by default
## Configuration
@ -50,11 +50,28 @@ Create a `config.json` file with your API tokens:
### API Token Setup
- **GitHub**: Create a Personal Access Token with `public_repo` and `user` scopes
- **GitHub**: Create a Personal Access Token with and `user:read` scope. Classic is preferred (see note)
- **GitLab**: Create a Personal Access Token with `read_api` scope
- **Codeberg**: Create an Access Token in your account settings
- **SourceHut**: No token required for public repositories. Specify repositories to track in the configuration.
Note on GitHub PATs. Some GitHub orgs will place additional restrictions on
PATs. If your token does not align with those policies, the GitHub stars API
will **silently discard** repos from that org. The only way to tell something
is off is by detecting the starred repositories count at
https://github.com/<username>?tab=stars is more than what is reported in the
application output.
There is a `checkForInaccessibleRepos` function in the GitHub provider that
can detect this, but is limited to the `aws` organization, which may or may
not apply in all situations. For this reason, it is included in the code, but
disabled. If needed, uncomment the call and choose a repo from your enterprise
of choice.
These org policies do not seem to effect classic tokens, so the best approach
with GitHub is to create and use a classic token instead of the new fine-grained
tokens.
## Testing
Run the test suite:

View file

@ -54,6 +54,10 @@ pub fn fetchReleases(self: *Self, allocator: Allocator) !ArrayList(Release) {
const starred_duration: u64 = @intCast(starred_end_time - starred_start_time);
std.log.debug("GitHub: Found {} starred repositories in {}ms", .{ starred_repos.items.len, starred_duration });
// Check for potentially inaccessible repositories due to enterprise policies
// try checkForInaccessibleRepos(allocator, &client, self.token, starred_repos.items);
std.log.debug("GitHub: Processing {} starred repositories with thread pool...", .{starred_repos.items.len});
const thread_start_time = std.time.milliTimestamp();
@ -423,6 +427,71 @@ fn compareReleasesByDate(context: void, a: Release, b: Release) bool {
return a.published_at > b.published_at;
}
fn checkForInaccessibleRepos(allocator: Allocator, client: *http.Client, token: []const u8, starred_repos: [][]const u8) !void {
const is_test = @import("builtin").is_test;
if (is_test) return; // Skip in tests
// List of repositories that are commonly affected by enterprise policies
const problematic_repos = [_][]const u8{
"aws/language-server-runtimes",
"aws/aws-cli",
"aws/aws-sdk-js",
"aws/aws-cdk",
};
const auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{token});
defer allocator.free(auth_header);
for (problematic_repos) |repo| {
// Check if this repo is in our starred list
var found_in_starred = false;
for (starred_repos) |starred_repo| {
if (std.mem.eql(u8, starred_repo, repo)) {
found_in_starred = true;
break;
}
}
if (!found_in_starred) {
// Check if we can access this repository directly to see if it's a policy issue
const check_url = try std.fmt.allocPrint(allocator, "https://api.github.com/user/starred/{s}", .{repo});
defer allocator.free(check_url);
const uri = std.Uri.parse(check_url) catch continue;
var server_header_buffer: [16 * 1024]u8 = undefined;
var req = client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
.extra_headers = &.{
.{ .name = "Authorization", .value = auth_header },
.{ .name = "Accept", .value = "application/vnd.github.v3+json" },
.{ .name = "User-Agent", .value = "release-tracker/1.0" },
},
}) catch continue;
defer req.deinit();
req.send() catch continue;
req.wait() catch continue;
if (req.response.status == .forbidden) {
// Try to read the error response for more details
const error_body = req.reader().readAllAlloc(allocator, 4096) catch "";
defer if (error_body.len > 0) allocator.free(error_body);
const stderr = std.io.getStdErr().writer();
if (std.mem.indexOf(u8, error_body, "enterprise") != null or
std.mem.indexOf(u8, error_body, "personal access token") != null or
std.mem.indexOf(u8, error_body, "fine-grained") != null)
{
stderr.print("GitHub: Repository '{s}' may be starred but is inaccessible due to enterprise policies: {s}\n", .{ repo, error_body }) catch {};
} else {
stderr.print("GitHub: Repository '{s}' is not accessible (HTTP 403): {s}\n", .{ repo, error_body }) catch {};
}
}
}
}
}
test "github provider" {
const allocator = std.testing.allocator;