The GAP package distribution is managed via this repository: specifically, it contains the metadata of all the GAP packages in the distribution. We also upload snapshots of the package distribution to appropriate release tags on this repository.
Test | GAP master |
---|---|
Released packages |
We automatically detect package updates provided these rules are followed:
- The
PackageInfoURL
in thePackageInfo.g
file of the current version of your package in the package distribution is valid and points to a copy of that file from the new version of your package. - In this
PackageInfo.g
file, theArchiveURL
is valid (i.e. when one adds a file extension fromArchiveFormats
it points to an archive containing your package).
We scan the PackageInfoURL
for all packages in the distribution once every hour for updates. When a new
version is detected this way, the package is downloaded and a new pull request
for the update is opened on this repository. A bunch of CI tests are then
started. Assuming they pass, a human will merge that PR, which means your
update is accepted. If a problem is detected, we will instead contact you to
discuss how to resolve it.
In the event that your package is to be moved to a new website, there are two ways to go about this that ensure we will still be able to pick up updates:
- If you still have access to the old location, simply upload the new
PackageInfo.g
file (containing the new URLs and of course also a new version number) in both the old and the new location. The system then will as usually automatically detect it, and once the update is accepted and merged, the system will use only the newPackageInfoURL
. - If this is not possible, you can also submit the update as if it was a new package, using one of the options listed in the next section.
There are several options how to do this.
-
(RECOMMENDED) Submit an issue to this repository, requesting that your package be added. Make sure to include a link to the
PackageInfo.g
file of your package. Note that such requests are visible to the anyone watching this repository. -
Send an email to [email protected], requesting that your package be added. Make sure to include a link to the
PackageInfo.g
file of your package. Note that such requests are visible to only to a small group of people listed on this web page.
In either case, we will evaluate your request and will inform you about the outcome of that (which may be: accept, accept after modifications, reject).
WARNING: The following instructions are only about the technical aspects of adding a new package. In general we may also want to impose other requirements for adding new packages to the distribution.
People who have write access to this repository should add new packages by creating a pull request for each new package. One way to do that is manually, as described above. Alternatively, this can be achieved via a GitHub workflow as follows:
- Go to https://github.com/gap-system/PackageDistro/actions/workflows/scan-for-updates.yml
- Click "Run workflow" once to open a popup menu. There is a field there accepting
a space separated list of
PackageInfo.g
URLs. Do so. - Click on the new green "Run workflow" button to actually trigger the workflow.
- After 2-3 minutes this should create a new pull request for each package you listed.
Once the PR is created, a bunch of CI tests are started. Once they are completed, a report is added to the PR which indicates whether the new package breaks something in GAP or other packages, and whether its tests pass. If all looks good, the PR may be merged by any maintainer.
The following is an overview of the internals of how everything works.
For each package in the GAP package distribution, there is a subdirectory of
the packages
directory whose name equals that of the package with all
letters turned to lower case. In that directory is a file called meta.json
which contains the metadata for that package as JSON.
For example, the metadata of ACE package is contained in packages/ace/meta.json
.
The content of the meta.json
file for package is obtained by reading its
PackageInfo.g
file in a GAP script, then turning this into JSON data where
possible (basically integers, strings, lists and records are converted to
their natural JSON counterparts; but e.g. functions are obviously not
convertible this way and thus are simply ignored). This is basically the same
form as used by the GAP release scripts to encode which packages are bundled
with a GAP release, except that there it is one big file, while here we have
one file per packages.
In addition to this, we also store the SHA256 checksum of the PackageInfo.g
file resp. of the first package archive under the keys PackageInfoSHA256
resp.
ArchiveSHA256
. Here, with "the first package archive", we mean that we
take the archive with first format extension specified by the ArchiveFormats
field of
the package info record.
For example, the SHA256 in this excerpt of a meta.json
file refers to the
.tar.gz
file
"ArchiveFormats": ".tar.gz .zip",
"ArchiveSHA256": "15c516d89863916ef8f4b0d5c68f5b79cb41b75741fc3b604a6a868569dcda38",
"ArchiveURL": "https://github.com/homalg-project/ToricVarieties_project/releases/download/2022-03-04/ToricVarieties",
All of this is driven by several GitHub Workflows
which automate most of the maintenance on the GAP package distribution. For
details on how they operate, have a look at the .yml
files in
.github/workflows
.
These workflows are in parts implemented by calling scripts in the tools
directory.
The scripts in the tools
directory are written in Python 3 or GAP. For the Python
scripts, you must make sure their prerequisites are installed, e.g. by invoking the
following command once from the root of this repository:
python -m pip install -r tools/requirements.txt
For information about what each script does, please consult its source, which should have comments explaining what it does and how to invoke it.
If you need to make changes to the Python code, note that we are using the
black
code formatter. Pull requests modifying
or adding Python code must run black
on all Python files in order to pass the
test suite and be merged.
The various scripts create and/oruse a bunch of auxiliary directories to store and exchange data:
_archives
is used to store copies of all package archives_pkginfos
stores copies of thePackageInfo.g
_releases
: TODO_unpacked_archives
: TODO
In a nutshell, when a new package update is received, we validates its metadata (including validating URLs in it), and run the testsuites of GAP and of all GAP packages in the package distribution. If any of these detects an issue, this is reported.
Some more details:
- if a package update is detected, we fetch its latest metadata and validate it
- This can be replicated manually by doing the following in an up-to-date clone
of the PackageDistro repository (substitute
example
by the name of your package)However this only works if you already made a release, as it downloads the metadata from the./tools/scan_for_updates.py example ./tools/validate_package.py example
PackageInfoURL
(see also #1024). - The checks this perform include
- check output of GAP function
ValidatePackageInfo
- verify version is greater than previous version and does not contain
dev
- verify release date is not less than previous release date
- verify release date is not in the future
- verify URLs are valid (currently
PackageInfoURL
,README_URL
, source archives) - validates source archives, including:
- must not contain absolute paths, or rather: all files in the archive must be contained in a single parent subdirectory
- must contain
PackageInfo.g
- must not contain symlinks
- check output of GAP function
- This can be replicated manually by doing the following in an up-to-date clone
of the PackageDistro repository (substitute
- clone the GAP repository and build GAP
- this (and all steps after this) is actually done twice, once for the latest
GAP
master
branch and once for the lateststable-X.Y
branch)
- this (and all steps after this) is actually done twice, once for the latest
GAP
- compile all packages that require it
- actually we skip
xgap
and also don't test it for technical reasons
- actually we skip
- start GAP, execute
LoadAllPackages()
, run GAP'stestinstall
test suite - for each package
pkgname
in the distribution- start GAP, do
LoadPackage("pkgname")
thenTestPackage("pkgname")
- start GAP, do
LoadPackage("pkgname" : OnlyNeeded)
thenTestPackage("pkgname")
- unfortunately quite some packages have issues with that as their test
suites actually require more than the minimal set of dependencies. We
currently are lenient there and include custom treatment for a bunch of
packages (for details see the "Run tests with OnlyNeeded" step in
.github/workflows/test-all.yml
)
- unfortunately quite some packages have issues with that as their test
suites actually require more than the minimal set of dependencies. We
currently are lenient there and include custom treatment for a bunch of
packages (for details see the "Run tests with OnlyNeeded" step in
- start GAP, do