filter to only releases in the last year
This commit is contained in:
parent
7b555e2162
commit
6edaa25cc5
1 changed files with 113 additions and 13 deletions
126
src/main.zig
126
src/main.zig
|
@ -18,6 +18,9 @@ const zeit = @import("zeit");
|
||||||
|
|
||||||
const Provider = @import("Provider.zig");
|
const Provider = @import("Provider.zig");
|
||||||
|
|
||||||
|
// Configuration: Only include releases from the last year in the output
|
||||||
|
const RELEASE_AGE_LIMIT_SECONDS: i64 = 365 * 24 * 60 * 60; // 1 year in seconds
|
||||||
|
|
||||||
pub const Release = struct {
|
pub const Release = struct {
|
||||||
repo_name: []const u8,
|
repo_name: []const u8,
|
||||||
tag_name: []const u8,
|
tag_name: []const u8,
|
||||||
|
@ -147,27 +150,38 @@ pub fn main() !u8 {
|
||||||
print("Found {} new releases from {s}\n", .{ result.releases.items.len, result.provider_name });
|
print("Found {} new releases from {s}\n", .{ result.releases.items.len, result.provider_name });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine existing and new releases
|
// Combine all releases (existing and new)
|
||||||
var all_releases = ArrayList(Release).init(allocator);
|
var all_releases = ArrayList(Release).init(allocator);
|
||||||
defer all_releases.deinit();
|
defer all_releases.deinit();
|
||||||
|
|
||||||
// Add new releases first (they'll appear at the top of the Atom feed)
|
// Add new releases
|
||||||
try all_releases.appendSlice(new_releases.items);
|
try all_releases.appendSlice(new_releases.items);
|
||||||
|
|
||||||
// Add existing releases (up to a reasonable limit to prevent Atom feed from growing indefinitely)
|
// Add all existing releases
|
||||||
const max_total_releases = 1000;
|
try all_releases.appendSlice(existing_releases.items);
|
||||||
const remaining_slots = if (new_releases.items.len < max_total_releases)
|
|
||||||
max_total_releases - new_releases.items.len
|
|
||||||
else
|
|
||||||
0;
|
|
||||||
|
|
||||||
const existing_to_add = @min(existing_releases.items.len, remaining_slots);
|
|
||||||
try all_releases.appendSlice(existing_releases.items[0..existing_to_add]);
|
|
||||||
|
|
||||||
// Sort all releases by published date (most recent first)
|
// Sort all releases by published date (most recent first)
|
||||||
std.mem.sort(Release, all_releases.items, {}, compareReleasesByDate);
|
std.mem.sort(Release, all_releases.items, {}, compareReleasesByDate);
|
||||||
|
|
||||||
// Generate Atom feed
|
// Filter releases by age in-place - zero extra allocations
|
||||||
|
const now = std.time.timestamp();
|
||||||
|
const cutoff_time = now - RELEASE_AGE_LIMIT_SECONDS;
|
||||||
|
|
||||||
|
var write_index: usize = 0;
|
||||||
|
const original_count = all_releases.items.len;
|
||||||
|
|
||||||
|
for (all_releases.items) |release| {
|
||||||
|
const release_time = parseReleaseTimestamp(release.published_at) catch 0;
|
||||||
|
if (release_time >= cutoff_time) {
|
||||||
|
all_releases.items[write_index] = release;
|
||||||
|
write_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shrink the array to only include filtered items
|
||||||
|
all_releases.shrinkRetainingCapacity(write_index);
|
||||||
|
|
||||||
|
// Generate Atom feed from filtered releases
|
||||||
const atom_content = try atom.generateFeed(allocator, all_releases.items);
|
const atom_content = try atom.generateFeed(allocator, all_releases.items);
|
||||||
defer allocator.free(atom_content);
|
defer allocator.free(atom_content);
|
||||||
|
|
||||||
|
@ -178,7 +192,7 @@ pub fn main() !u8 {
|
||||||
|
|
||||||
// Log to stderr for user feedback
|
// Log to stderr for user feedback
|
||||||
std.debug.print("Found {} new releases\n", .{new_releases.items.len});
|
std.debug.print("Found {} new releases\n", .{new_releases.items.len});
|
||||||
std.debug.print("Total releases in feed: {}\n", .{all_releases.items.len});
|
std.debug.print("Total releases in feed: {} (filtered from {} total, showing last {} days)\n", .{ all_releases.items.len, original_count, @divTrunc(RELEASE_AGE_LIMIT_SECONDS, 24 * 60 * 60) });
|
||||||
std.debug.print("Updated feed written to: {s}\n", .{output_file});
|
std.debug.print("Updated feed written to: {s}\n", .{output_file});
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -761,6 +775,92 @@ test {
|
||||||
std.testing.refAllDecls(@import("xml_parser_tests.zig"));
|
std.testing.refAllDecls(@import("xml_parser_tests.zig"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Age-based release filtering" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
|
||||||
|
const now = std.time.timestamp();
|
||||||
|
const one_year_ago = now - RELEASE_AGE_LIMIT_SECONDS;
|
||||||
|
const two_years_ago = now - (2 * RELEASE_AGE_LIMIT_SECONDS);
|
||||||
|
|
||||||
|
// Create releases with different ages
|
||||||
|
const recent_release = Release{
|
||||||
|
.repo_name = "test/recent",
|
||||||
|
.tag_name = "v1.0.0",
|
||||||
|
.published_at = try std.fmt.allocPrint(allocator, "{}", .{now - 86400}), // 1 day ago
|
||||||
|
.html_url = "https://github.com/test/recent/releases/tag/v1.0.0",
|
||||||
|
.description = "Recent release",
|
||||||
|
.provider = "github",
|
||||||
|
};
|
||||||
|
defer allocator.free(recent_release.published_at);
|
||||||
|
|
||||||
|
const old_release = Release{
|
||||||
|
.repo_name = "test/old",
|
||||||
|
.tag_name = "v0.1.0",
|
||||||
|
.published_at = try std.fmt.allocPrint(allocator, "{}", .{two_years_ago}),
|
||||||
|
.html_url = "https://github.com/test/old/releases/tag/v0.1.0",
|
||||||
|
.description = "Old release",
|
||||||
|
.provider = "github",
|
||||||
|
};
|
||||||
|
defer allocator.free(old_release.published_at);
|
||||||
|
|
||||||
|
const borderline_release = Release{
|
||||||
|
.repo_name = "test/borderline",
|
||||||
|
.tag_name = "v0.5.0",
|
||||||
|
.published_at = try std.fmt.allocPrint(allocator, "{}", .{one_year_ago + 3600}), // 1 hour within limit
|
||||||
|
.html_url = "https://github.com/test/borderline/releases/tag/v0.5.0",
|
||||||
|
.description = "Borderline release",
|
||||||
|
.provider = "github",
|
||||||
|
};
|
||||||
|
defer allocator.free(borderline_release.published_at);
|
||||||
|
|
||||||
|
const releases = [_]Release{ recent_release, old_release, borderline_release };
|
||||||
|
|
||||||
|
// Test filtering logic
|
||||||
|
var filtered = ArrayList(Release).init(allocator);
|
||||||
|
defer filtered.deinit();
|
||||||
|
|
||||||
|
const cutoff_time = now - RELEASE_AGE_LIMIT_SECONDS;
|
||||||
|
|
||||||
|
for (releases) |release| {
|
||||||
|
const release_time = parseReleaseTimestamp(release.published_at) catch 0;
|
||||||
|
if (release_time >= cutoff_time) {
|
||||||
|
try filtered.append(release);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should include recent and borderline, but not old
|
||||||
|
try std.testing.expectEqual(@as(usize, 2), filtered.items.len);
|
||||||
|
|
||||||
|
// Verify the correct releases were included
|
||||||
|
var found_recent = false;
|
||||||
|
var found_borderline = false;
|
||||||
|
var found_old = false;
|
||||||
|
|
||||||
|
for (filtered.items) |release| {
|
||||||
|
if (std.mem.eql(u8, release.repo_name, "test/recent")) {
|
||||||
|
found_recent = true;
|
||||||
|
} else if (std.mem.eql(u8, release.repo_name, "test/borderline")) {
|
||||||
|
found_borderline = true;
|
||||||
|
} else if (std.mem.eql(u8, release.repo_name, "test/old")) {
|
||||||
|
found_old = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try std.testing.expect(found_recent);
|
||||||
|
try std.testing.expect(found_borderline);
|
||||||
|
try std.testing.expect(!found_old);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "RELEASE_AGE_LIMIT_SECONDS constant verification" {
|
||||||
|
// Verify the constant is set to 1 year in seconds
|
||||||
|
const expected_year_in_seconds = 365 * 24 * 60 * 60;
|
||||||
|
try std.testing.expectEqual(expected_year_in_seconds, RELEASE_AGE_LIMIT_SECONDS);
|
||||||
|
|
||||||
|
// Verify it's approximately 31.5 million seconds (1 year)
|
||||||
|
try std.testing.expect(RELEASE_AGE_LIMIT_SECONDS > 31_000_000);
|
||||||
|
try std.testing.expect(RELEASE_AGE_LIMIT_SECONDS < 32_000_000);
|
||||||
|
}
|
||||||
|
|
||||||
// Import timestamp tests
|
// Import timestamp tests
|
||||||
test {
|
test {
|
||||||
std.testing.refAllDecls(@import("timestamp_tests.zig"));
|
std.testing.refAllDecls(@import("timestamp_tests.zig"));
|
||||||
|
|
Loading…
Add table
Reference in a new issue