# Moving third-party packages to Codeberg

**URL:** <https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312>\
**Category:** General\
**Tags:** question\
**Created:** [July 7, 2026, 4:17pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312 "2026-07-07T16:17:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![neilvandyke](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/neilvandyke/32/2694_2.png) [@neilvandyke](https://racket.discourse.group/u/neilvandyke)\
**Post date:** [July 7, 2026, 4:17pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/1 "2026-07-07T16:17:28Z")

</div>

Hi. Does anyone knowledgeable about the Racket package system and Git want to comment on this plan?

I want to move 37+ Racket packages I wrote to Codeberg (which is like GitHub or GitLab, but warmer and fuzzier). The Racket package server is currently getting most of them from my Web site, not from Git. Some of these packages are in use by others. You can see most of them here: [neilvandyke.org - Scheme & Racket](https://www.neilvandyke.org/racket/)

I'd like to have this migration work the first time, without breaking anyone's dependencies, and with a minimum of effort.

Example plan for package `mcfly`:

1. I have releases: mcfly--2-0.zip mcfly--2-1.zip mcfly--2-2.zip

2. Make repo: [codeberg.org/neilvandyke/racket-mcfly](http://codeberg.org/neilvandyke/racket-mcfly)

3. Extract .zips to git tags: v2.0 v2.1 v2.2

4. Add homepage/doc link in Codeberg.

5. Change Racket pkg system entry to use repo.

6. Some kind of measure to discourage the recent flood of LLM-generated pull requests that are drowning some other open source projects.

Then I would do the other few dozen packages like that.

If that exact plan should work smoothly, I can maybe do it in a couple hours. Putting on my software engineer hat, what I want to avoid is doing it but then later having to abruptly do urgent firefighting because something broke. Or having to go back and do something additional to each package.

Comments appreciated. Please feel free to reply here, or (I'll see it sooner) on [https://mastodon.online/@neilvandyke/116756820844767929](https://mastodon.online/@neilvandyke/116756820844767929) or via email.

P.S., I also have a few unreleased packages, which I might polish up and release if this goes smoothly.

Thanks,  
Neil V.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [July 7, 2026, 4:48pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/2 "2026-07-07T16:48:15Z")

</div>

I don't see any particular issues with that plan.

> [@neilvandyke](#):
>
> 1. Extract .zips to git tags: v2.0 v2.1 v2.2

Obviously this step is easier if the package sources are already tracked by Git (or another VCS that Git knows how to import from), but this also seems a reasonable way to map the existing archives into version control.

I don't know that the tags will matter too much to the Racket package server (though as above they'll be nice for humans) if you plan on pointing it at the "main" branch; if you plan to use another strategy\[1\], then you should be able to have the package server do something with the tags.

* * *

1. Recall that [Raco and Git and humans sometimes have differing notions of versions](https://github.com/drym-org/qi/wiki/Qi-Meeting-Apr-12-2024#an-early-release)—and unless library consumers use a specific-enough URL to pin to a particular source revision, Raco will happily given them anything newer than the `#:version` constraint in their `info.rkt` (if any).

---

<div class="post-metadata">

**Author:** ![neilvandyke](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/neilvandyke/32/2694_2.png) [@neilvandyke](https://racket.discourse.group/u/neilvandyke)\
**Post date:** [July 7, 2026, 7:46pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/3 "2026-07-07T19:46:09Z")

</div>

Good point about versions. One of the reasons for the Git tags (and for me increasing the priority to move to Codeberg) is that there was a recent headache involving versioning and the Racket package server.

> <https://github.com/jeapostrophe/racket-langserver/issues/211>
>
> Hi! You can safely ignore this bug report if you think this is a non issue. 
> 
> Th…e issue I have with some dependencies of \`racket-langserver\` is that they are notoriously hard to package. Namely the https://pkgs.racket-lang.org/package/html-parsing package. Neil, the maintainer of the package published a unversioned ZIP file on their website. Now, I'm all for distributed sources but there are annoying issues with current state.
> 
> Unversioned sources are notoriously hard to package, especially for automated package creation, like we do in gentoo-racket-overlay (the project basically shovels the whole Racket pkg db to Gentoo ebuilds thus making them installable via Gentoo's pkg manager - Portage). this is because Gentoo (and almost all other Linux pkgs) require strictly set versions and sources. The only escape from this right now is to take what Neil (or other devs publish) and mirror it on some own hosting. Here I have to also state that even though we have a lot of unversioned packages on pkgs.racket.org \*\*they use git\*\* and we can work with git but can not work with pure ZIPfiles.
> 
> So I just want to state it as a heads up. What could we do in this case? - Dunno. The best would be for Neil to publish versioned Racket packages, at least then "we" (or rather my Gentoo-Racket project and similar initiatives) do not have to mirror. The other idea would be to drop the html-parsing dependency but we probably do not want that :)
> 
> Thanks a lot! And thanks to Neil for all his pkgs - if you are reading this!
> 
> CC @neilvandyke

It's also unclear to me whether the Racket package server is preserving old versions of packages.

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [July 7, 2026, 8:37pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/4 "2026-07-07T20:37:46Z")

</div>

> [@neilvandyke](#):
>
> 1. Some kind of measure to discourage the recent flood of LLM-generated pull requests that are drowning some other open source projects.

Not to jinx myself but so far I have not experienced any automated (a.k.a. "agentic" ... pardon me I throw up in my mouth a little while typing that 😄) pull requests.

I did get one human submitting a PR, the code for which was "AI" assisted. But just once. I updated the README to explain why I couldn't accept such PRs (TL;DR: no provenance).

Hopefully this factor won't turn out to be a big practical problem for you, either!

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [July 7, 2026, 9:23pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/5 "2026-07-07T21:23:14Z")

</div>

> [@neilvandyke](#):
>
> Example plan for package `mcfly`:

This plan sounds great to me!

I've thought some about these sorts of things in the context of (very, very slowly) integrating Racket with Guix and archival preservation. I won't have time to write a whole lot of detail this week, but the bottom line is this sounds like an excellent direction, and many additional tools are able to help with archiving software in Git repositories than in ad hoc zip/tar/etc. archives on a website.

> [@benknoble](#):
>
> unless library consumers use a specific-enough URL to pin to a particular source revision, Raco will happily given them anything newer than the `#:version` constraint in their `info.rkt` (if any)

While it is possible for a library consumer to use a sufficiently-specific URL in-band to achieve pinning, it is usually better to do any needed pinning out-of-band through a catalog that maps the package name to the pinned URL. (And maybe that's what you had in mind, after all: the in-band way is fairly obscure, I think.)

> [@neilvandyke](#):
>
> It's also unclear to me whether the Racket package server is preserving old versions of packages.

The package server doesn't do anything about old versions of packages.

A good mental model of the package catalog protocol is a dictionary mapping “package names” to concrete, non-name “package sources.” That one layer of indirection turns out to be very useful for a variety of purposes. The Racket release process involves creating a catalog of all the packages in the release at the released version, which lets e.g. “minimal Racket” 9.2, configured to try the 9.2 release catalog first, install the `drracket` package and get the same libraries as the Racket 9.2 “main distribution.” The same catalog mechanism works for off-line builds, since the catalog can map names to local filesystem locations. In fact, that also gets used in the release process: a source distribution finds its bundled packages for initial installation through an off-line catalog.

I am enthusiastic about the fact that the catalog protocol does one simple job well. Nonetheless there are additional features one reasonably might want in a package system, like preserving old versions. My view is that the features are best approached by layering on top of the catalog protocol, rather “piling feature on top of feature” in the core protocol.

This is where I think it is very helpful, @neilvandyke, that you are planning to move your packages to Git. While a human can look at the URL for mcfly--2-1.zip in the catalog and infer the existence of mcfly--2-0.zip (and then hope that either you or e.g. the Internet Archive has preserved it), it would be less obvious to a tool, let alone if some less experienced and conscientious author had just published my-great-package.zip with no contextual clues. Using a Git repository ties the latest code to older and alternate versions, with the Racket package “checksum” recording the Git commit hash. It then becomes much more viable to leverage the work other communities have been doing to archive software in Git repositories.

(Other kinds of version-control repositories would have similar technical merits: Git is just the lingua franca at the moment.)

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [July 8, 2026, 3:42pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/6 "2026-07-08T15:42:25Z")

</div>

@neilvandyke With the status quo system, I think the idea/opinion is:

- If you're _adding_ new features/functionality, bump the version number. Dependents who need those new features can bump their `deps` to require your higher version number.

- If you're _deleting_ or _changing_ (in a breaking way) _existing_ features... well, please don't do that to an existing package. Backward compatibility is important. Breaking dependents isn't nice. Instead, please make a new package with a new name, and keep the old package available under the original name.

* * *

Me? I think the system's opinion is wise and reflects the reality that dependency relationships are social not just technological.

But of course that's not everyone's opinion, or even the majority opinion.

Other ideas could be layered on top, for sure, as @LiberalArtist describes.

@neilvandyke One thing you could do is, go with the flow, status quo, and make a distinct Racket package for each older version, with something about the version number in the package name. IIUC each package could point back to some git version/branch/checksum in the same _repo_.

---

<div class="post-metadata">

**Author:** ![dominik.pantucek](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/dominik.pantucek/32/144_2.png) [@dominik.pantucek](https://racket.discourse.group/u/dominik.pantucek)\
**Post date:** [July 11, 2026, 9:07am UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/7 "2026-07-11T09:07:01Z")

</div>

Are you using some CI/CD workflows in some of your packages? If so, do you have any plans to migrate these to Forgejo actions as supported by Codeberg?

We made a similar decision with one project (multiple packages) and I am also inclined to migrate my packages there. However some coordinated Racket support might help us all. I am thinking about specific reusable (cached) actions and/or container images that would be usable Codeberg-wide for running tests and/or compiling documentation for packages not on package server (or for compiling development snapshots documentation etc...).

Any thoughts?

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [July 17, 2026, 6:32pm UTC](https://racket.discourse.group/t/moving-third-party-packages-to-codeberg/4312/8 "2026-07-17T18:32:38Z")

</div>

> [@neilvandyke](#):
>
> 1. Extract .zips to git tags: v2.0 v2.1 v2.2

> [@greghendershott](#):
>
> @neilvandyke One thing you could do is, go with the flow, status quo, and make a distinct Racket package for each older version, with something about the version number in the package name. IIUC each package could point back to some git version/branch/checksum in the same _repo_.

You definitely _could_ do that, but it would be more than is necessary to provide the equivalent of the status quo. IIUC, @neilvandyke currently has registered packages like `mcfly` once each, with the names pointing to sources like `mcfly--2-2.zip`. Sources for older versions remain available at the corresponding URLs like `mcfly--2-1.zip`, but anyone wanting to use them must do so manually, using the explicit URL or a catalog they have built (or [https://racksnaps.defn.io](https://racksnaps.defn.io), etc, etc), just like someone who wants to specify `mcfly--2-2.zip` even if future releases become available.

I think just providing the older releases as tags in the Git repository covers all the use-cases supported by the current setup, with an equivalent level of discoverability for humans. And I would suggest that other use-cases are niche enough that it would be better to address them only in response to a concrete need. The few packages I know of that try those sorts of things (which mostly respond to considerations like keeping code from a published paper working exactly) run into other downsides, and the tradeoffs seem harder to balance in the abstract.

On the catalog side, you could point the Git package source to a particular tag like `v2.2`, but you could equally well point to a `main` or `stable` branch holding the tagged releases, which would save having to update the catalog registration separately when releasing new versions.

I **would** suggest arranging to put all of the old releases on the same branch, so that Git understands the parent relationships between them. (Maybe that's what you'd do be default.) You could consider if you want to set the Git `AuthorDate` (vs. `CommitDate`) to the original release dates, if you want to be really fancy.

* * *

> [@greghendershott](#):
>
> Other ideas could be layered on top, for sure, as @LiberalArtist describes.

Tangentially, I realized the [Package Build Service](https://pkg-build.racket-lang.org/about.html) is an example of the kind of design I meant by “layering on top” of the core package catalog protocol. It is responsible for many useful features of the overall experience of Racket’s package system: generating the on-line documentation is probably the most obvious, but it also does CI testing and distributes packages in pre-built form. But it does all that without changing the core system. In some sense, you could think of it as a function from package catalog to package catalog.
