Deploying from GitHub, GitLab, and Forgejo
Mirror a repository from a git provider and deploy it on every push.
A project can mirror a repository on GitHub, GitLab, Gitea, or Forgejo
(including Codeberg). The provider calls picd's webhook on every push, and
picd fetches the repository and deploys it the same way a
git push to picd does.
Set the upstream #
1ssh cd.pico.sh upstream set web git@github.com:alice/web.git
creates the project if it doesn't exist yet, and prints what to add to the provider:
Upstream: git@github.com:alice/web.git
Deploy key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
Add it to the repository as a read-only deploy key.
Webhook: https://cd.pico.sh/webhooks/alice/web
Secret: 5f0c...
Send push events as JSON. On GitLab, the secret is the token.
The upstream can be an https:// URL, an ssh:// URL, or
git@host:path. picd fetches SSH URLs with the project's deploy key, or
with your own key. Public repositories can use
https:// and skip the deploy key.
Add the deploy key and webhook #
On GitHub, under the repository's Settings:
- Deploy keys: add the deploy key, leaving write access off.
- Webhooks: add the webhook URL as the payload URL, with content type
application/json, the secret, and only the push event.
On GitLab, under the project's Settings:
- Repository, Deploy keys: add the deploy key, leaving write access off.
- Webhooks: add the webhook URL, put the secret in Secret token, and trigger on push events.
On Gitea and Forgejo, under the repository's Settings:
- Deploy keys: add the deploy key, leaving write access off.
- Webhooks: add a Gitea or Forgejo webhook with the webhook URL, content
type
application/json, the secret, and push events.
Then deploy what's there now:
1ssh cd.pico.sh upstream sync web
Using your own SSH key #
The fetch runs in your environment, with the ~/.ssh/config and keys in
your home directory. It offers your keys
before the deploy key, so a key that can already read the repository, such
as a machine user's or one on a self-hosted forge, works without adding the
deploy key:
1ssh cd.pico.sh
2ssh-keygen -t ed25519 -N '' -f ~/.ssh/forge
3cat >> ~/.ssh/config <<'EOF'
4Host forge
5 HostName git.example.com
6 Port 2222
7 User git
8 IdentityFile ~/.ssh/forge
9EOF
10ssh -T forge
11exit
12ssh cd.pico.sh upstream set web forge:team/web.git
Keys need an empty passphrase, since no one is there to type it. Keys named
~/.ssh/id_ed25519, id_ecdsa, or id_rsa are offered without a config
entry. The first fetch from a host records its key in ~/.ssh/known_hosts.
Set StrictHostKeyChecking yes in your config to accept only keys already
there.
Private https:// upstreams work with a git credential helper, such as
git config --global credential.helper store with a token in
~/.git-credentials.
What a push does #
On each push, picd fetches every branch and tag from the upstream into the
project's repository, replacing what's there and removing branches the
upstream no longer has. If the push changed the branch the project deploys,
picd deploys it. The deploy runs after picd answers the webhook, so the
provider shows 202 Accepted whether or not the deploy works.
upstream shows the last webhook deploy and its output:
1ssh cd.pico.sh upstream web
If more pushes arrive while a project is deploying, picd deploys them together once the current deploy finishes.
A new project deploys the upstream's default branch. Change it with
branch set like any other project. Pushing to picd
directly still works, but the next fetch replaces its branches with the
upstream's.
Stop mirroring #
1ssh cd.pico.sh upstream unset web
stops fetching and forgets the deploy key and secret. The project and its repository stay. Remove the deploy key and webhook from the provider too.