Skip to content

Commit f5e9177

Browse files
authored
Merge pull request #2150 from zklaus/describe-infrastructure-role-in-packaging
Add description of role of infrastructure in package building
2 parents 67e571a + 12e02ab commit f5e9177

File tree

1 file changed

+160
-4
lines changed

1 file changed

+160
-4
lines changed

docs/maintainer/infrastructure.md

Lines changed: 160 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,7 @@ the bot now runs directly in `regro/cf-scripts`.
286286

287287
This web application powers several services, like:
288288

289-
- the `@conda-forge-admin, please ...` commands
290-
- the `@conda-forge-linter` bot
289+
- the `@conda-forge-admin` bot and its `@conda-forge-admin, please ...` commands
291290
- the `cf-staging` to `conda-forge` validation (plus copy)
292291
- status monitoring
293292

@@ -641,6 +640,163 @@ uploaded from the new feedstock, by design.
641640
Once this is done correctly and the package is uploaded,
642641
you can then request the conda-forge core devs to archive the old feedstock.
643642

643+
## Stages of package building and involved infrastructure
644+
645+
Packages in conda-forge are almost[^manual-builds] always built through CI.
646+
However, when a new package enters conda-forge for the first time, it does so via a pull request in the [`staged-recipes` repository](#staged-recipes), whereas every new build of the package after that is built in its repository, the so-called feedstock.
647+
Both places use slightly different CI setups and interact with the infrastructure accordingly.
648+
Hence, we first describe the interaction at the start of a new package and then for existing packages in their respective feedstocks.
649+
650+
[^manual-builds]:
651+
Very few packages cannot be built through CI due to special resource
652+
requirements. These packages may be built and uploaded manually following the rules
653+
laid out in [CFEP-3](https://github.com/conda-forge/cfep/blob/main/cfep-03.md).
654+
655+
### Initial submission to staged-recipes
656+
657+
The `conda-forge/staged-recipes` repository uses several pieces of infrastructure.
658+
659+
On pull requests:
660+
661+
- Package building pipelines. These are slightly different than the ones running in feedstocks (they are not automatically generated by `conda-smithy`, but they do use the same underlying components).
662+
- The linter is provided by `conda-smithy recipe-lint`, run by `@conda-forge-admin`.
663+
- Auto-labeling logic, run by Github Actions workflows.
664+
665+
Authenticated services involved:
666+
667+
- Github, with permissions for:
668+
- PR labeling
669+
- Azure Pipelines
670+
671+
The conversion of new recipes in `staged-recipes` to their respective feedstocks
672+
happens in a cron job run by `admin-requests`. For more details see [admin-requests](#admin-requests).
673+
As part of the feedstock creation, the new feedstock receives a webhook connecting it with the [webservices](#admin-web-services).
674+
675+
### Feedstock changes
676+
677+
A feedstock can receive changes for several reasons.
678+
679+
Pushes to `main` or other branches:
680+
681+
- The automated initialization commits following approval in `staged-recipes`.
682+
These are generated by `conda-smithy` and pushed by the automation in `admin-requests`.
683+
- Automated maintenance commits triggered from `admin-migrations`.
684+
- Rerender requests are handled by instances of `conda-forge/webservices-dispatch-action` and triggered by the [webservices](#admin-web-services).
685+
686+
Automatic pull requests can be opened by...
687+
688+
- `@conda-forge-admin`, responding to some issues with titles like `@conda-forge-admin, please...`.
689+
- `@regro-cf-autotick-bot`, handling migrations and new versions being available.
690+
691+
...and closed by:
692+
693+
- `conda-forge/automerge-action`, if labeled accordingly.
694+
695+
On an open pull request:
696+
697+
- The building pipelines (more [below](#package-building)).
698+
- The linter is provided by `conda-smithy recipe-lint`, run by `@conda-forge-admin`.
699+
- The `@conda-forge-admin, please...` command comments, answered by `@conda-forge-admin`.
700+
701+
On issues:
702+
703+
- `@conda-forge-admin, please...` command issues, handled by `@conda-forge-admin`.
704+
705+
### Package building {#package-building}
706+
707+
The pipelines that build conda packages are used for both pull requests and push events in `main` and other branches.
708+
The only difference is that the packages built during a pull request are not uploaded to the staging channel.
709+
Maintaining these up-to-date across all feedstocks involves several repositories:
710+
711+
- `conda-smithy` is in charge of generating the CI pipelines themselves, together with the supporting scripts and configuration files.
712+
These pipelines and scripts can rely on code and data defined in the repositories below.
713+
- `conda-forge-ci-setup-feedstock` provides the code needed to prepare and homogenize the CI runners across providers.
714+
It also does some checks before the artifacts are uploaded to `cf-staging`.
715+
- `conda-forge-pinning-feedstock` defines which versions are supported for a number of runtimes and libraries, as well as the compilers used for certain languages and platforms.
716+
- `docker-images` builds the standardized container images for Linux runners.
717+
This repository has additional authentication needs for Docker Hub, Quay.io.
718+
719+
The pipelines can run on several CI providers supported by `conda-smithy`, including:
720+
721+
- Azure DevOps Pipelines
722+
- Travis CI
723+
- Circle CI
724+
- Appveyor
725+
- Self-hosted Github Actions runners
726+
727+
Registration of hooks and triggers is also done by the `conda-smithy` app.
728+
729+
:::tip
730+
`conda-smithy` supports more CI providers.
731+
Check [its repository](https://github.com/conda-forge/conda-smithy) for more details.
732+
:::
733+
734+
Authenticated services involved:
735+
736+
- Anaconda.org uploads to `cf-staging`
737+
738+
### Package validation and publication
739+
740+
Once built on `main` (or other branches), the conda packages are uploaded to an intermediary channel named `cf-staging`.
741+
From there, our webservices (`conda-forge/conda-forge-webservices`) does the following:
742+
743+
- The logic checks the feedstock token to authenticate a legitimate request.
744+
- The logic checks that the hash sum of the package on `cf-staging` against
745+
the value computed in the CI to ensure the artifact to be copied is the same.
746+
- The logic checks that the feedstock is allowed to push the package using
747+
the `conda-forge/feedstock-outputs` repo.
748+
- If all three checks pass, the webservices copies the artifacts from `cf-staging` to `conda-forge`.
749+
750+
Authenticated services involved:
751+
752+
- Anaconda.org uploads to `conda-forge` and `cf-staging`
753+
- The `conda-forge-webservices` app deployment itself (currently at Heroku)
754+
755+
### Post-publication
756+
757+
Once uploaded to anaconda.org/conda-forge, packages are not immediately available to CLI clients.
758+
They have to be replicated in the Content Distribution Network (CDN).
759+
This step should ideally take around 15 minutes. In some circumstances, longer delays are possible. Check [conda-forge.org/status](https://conda-forge.org/status) in case of doubt.
760+
761+
After CDN replication, most packages available on anaconda.org/conda-forge won't suffer any further modifications.
762+
However, in some cases, maintainers might need to perform some actions on the published packages:
763+
764+
- Patching their repodata
765+
- Marking them as broken
766+
767+
#### Repodata patch
768+
769+
The metadata for `conda` packages is initially contained in each package archive (under `info/`).
770+
`conda index` iterates over the published `conda` packages, extracts the metadata and consolidates all the found JSON blobs into a single JSON file: `repodata.json`.
771+
This is where the hashes and file sizes are added too.
772+
This is the metadata file that the CLI clients download initially to _solve_ the environment.
773+
774+
Since the metadata is external to the package files, some details can be modified without rebuilding packages, which simplifies some maintenance tasks notably.
775+
776+
Repodata patches are created in `conda-forge/conda-forge-repodata-patches-feedstock`, which generates (and uploads) a regular `conda` package as a result:
777+
[`conda-forge-repodata-patches`](https://anaconda.org/conda-forge/conda-forge-repodata-patches/files).
778+
Each of these timestamped packages contains the patch instructions for each channel subdir on conda-forge.
779+
The Anaconda infrastructure takes the JSON files from these packages and applies them on top of the vanilla `repodata.json` (which remains available for download as `repodata_from_packages.json`).
780+
781+
Since `conda-forge-repodata-patches-feedstock` operates as a regular feedstock for package publication, there are no further infrastructural details to cover.
782+
783+
#### Mark a package as broken
784+
785+
Sometimes a package is faulty in ways that a repodata patch cannot amend (e.g. bad binary).
786+
In these cases, conda-forge does not remove packages from Anaconda.org.
787+
Instead, it marks them with the `broken` label, which has a special meaning:
788+
packages labeled as such will be removed from the repodata via automated patches.
789+
This action is reversible and doesn't change the direct URL of the artifact, which
790+
can always be downloaded from e.g. a lockfile.
791+
792+
The main repository handling this is `conda-forge/admin-requests`, which features different
793+
Github Actions workflows running every 15 minutes.
794+
795+
For this task, the Github Action workflow needs access to:
796+
797+
- Anaconda.org, to add (or remove) labels
798+
- Github, to modify and commit the input files after success
799+
644800
## Inventory of services & providers
645801

646802
### Github resources
@@ -698,15 +854,15 @@ Most of them are associated with a feedstock, but there are a few special ones t
698854

699855
- [`conda-forge-admin`](https://github.com/conda-forge-admin)
700856
- [`conda-forge-daemon`](https://github.com/conda-forge-daemon)
701-
- [`conda-forge-linter`](https://github.com/conda-forge-linter)
702857
- [`regro-cf-autotick-bot`](https://github.com/regro-cf-autotick-bot)
703858

704859
:::info
705860
These accounts exist but are not in active usage anymore:
706861

707-
- [`conda-forge-drone-ci`](https://github.com/conda-forge-drone-ci)
708862
- [`conda-forge-bot`](https://github.com/conda-forge-bot)
709863
- [`conda-forge-coordinator`](https://github.com/conda-forge-coordinator)
864+
- [`conda-forge-drone-ci`](https://github.com/conda-forge-drone-ci)
865+
- [`conda-forge-linter`](https://github.com/conda-forge-linter)
710866
- [`conda-forge-manager`](https://github.com/conda-forge-manager)
711867
- [`conda-forge-status`](https://github.com/conda-forge-status)
712868

0 commit comments

Comments
 (0)