I’m looking for something like GitHub’s user activity indicator that gathers information from a list of git repositories regardless of where they are hosted (as long as they are public), that I can put on my webpage, kind of as a thing to show what I’m working on at the moment.
Is this a thing that already exists? I’d started writing one a while ago but instead of reviving that it would be great if there’s something that already exists and I can just use :^)
@2xsaiko RSS/Atom feeds were developed for this use case. GitHub, GitLab, Codeberg (Forgejo), Sourcehut, even cgit and git’s own gitweb serve feeds. For example here’s my GitHub account: https://github.com/ollytom.atom
my main OSS project: https://git.olowe.co/streaming/atom/Atom feeds are widely supported (it’s how I found this post!) and there are many libraries/apps/plugins for aggregation. Robust old tech. And no need to limit feeds to Git activity if you don’t want to :) Good luck!
Oh nice, I wasn’t aware there were RSS feeds for git repositories! Makes sense though. I’ll look into this.
OpenHub is vaguely working like this. It is meant to accumulate all your development work throughout the Internet. E.g. my profile there looks like this:
https://openhub.net/accounts/mbirth
It’s not for self-hosting, though, as far as I’m aware.
This looks interesting too, maybe a bit overkill for what I’m looking for though. I’ll take a look, thanks!
Probably not, since Git is federated and decentralized. There are no git “accounts”. Git asks for your name and email but those are basically meaningless unless the repository hosting platform does something with them like ties them to an account identity.
You could maybe use the GitHub activity view by also mirroring your projects from elsewhere onto GH
There don’t have to be, it would be completely fine just filtering commits by author email. Or maybe even signing key.
You might get more responses by cross-posting this to !programming@programming.dev
I asked chatgpt to write a go program for this, this looks roughly correct (I have used both libraries before) obviously this won’t be enough for your particular use case. I imagine you can integrate an RSS feed to your site, however if you’re using something like hugo perhaps output it as a csv.
Super low effort but a good start I think:
package main import ( "fmt" "log" "os" "strings" "time" git "github.com/go-git/go-git/v5" rss "github.com/jteeuwen/go-pkg-rss" ) const ( timeout = 5 // timeout in seconds for the RSS feed generation ) // Repository represents a git repository with its URL type Repository struct { URL string } // Repositories is the list of git repositories var Repositories = []Repository{ {URL: "https://github.com/owner/repo1"}, {URL: "https://github.com/owner/repo2"}, // Add more repositories here } // FetchLatestTag fetches the latest tag from a git repository func FetchLatestTag(repoURL string) (string, string, error) { // Clone the repository to a temporary directory dir, err := os.MkdirTemp("", "repo") if err != nil { return "", "", err } defer os.RemoveAll(dir) _, err = git.PlainClone(dir, true, &git.CloneOptions{ URL: repoURL, Progress: os.Stdout, }) if err != nil { return "", "", err } repo, err := git.PlainOpen(dir) if err != nil { return "", "", err } tags, err := repo.Tags() if err != nil { return "", "", err } var latestTag string var latestCommitTime time.Time err = tags.ForEach(func(ref *plumbing.Reference) error { tag := ref.Name().Short() commit, err := repo.CommitObject(ref.Hash()) if err != nil { return err } if commit.Committer.When.After(latestCommitTime) { latestCommitTime = commit.Committer.When latestTag = tag } return nil }) if err != nil { return "", "", err } return latestTag, latestCommitTime.Format(time.RFC1123Z), nil } // GenerateRSS generates an RSS feed from the latest tags of the repositories func GenerateRSS() string { feed := rss.Feed{ Title: "Latest Tags from Git Repositories", Link: &rss.Link{Href: "http://example.com/"}, Description: "This feed provides the latest tags from a list of git repositories.", Created: time.Now(), } for _, repo := range Repositories { tag, date, err := FetchLatestTag(repo.URL) if err != nil { log.Printf("Error fetching latest tag for repository %s: %v", repo.URL, err) continue } feed.Items = append(feed.Items, &rss.Item{ Title: fmt.Sprintf("Latest tag for %s: %s", repo.URL, tag), Link: &rss.Link{Href: repo.URL}, Description: fmt.Sprintf("The latest tag for repository %s is %s, created on %s.", repo.URL, tag, date), Created: time.Now(), }) } var rssFeed strings.Builder rssFeed.WriteString(xml.Header) if err := feed.Write(&rssFeed); err != nil { log.Fatalf("Error generating RSS feed: %v", err) } return rssFeed.String() } func main() { rssFeed := GenerateRSS() fmt.Println(rssFeed) }