| 1 | --- |
| 2 | title: Packages |
| 3 | description: Publish and install packages beside your code, with the same people, roles and tokens. |
| 4 | --- |
| 5 | |
| 6 | A workspace can publish packages to g1t and install them from it, beside |
| 7 | the code they are built from: container images, npm packages, Rust |
| 8 | crates, Maven artifacts, NuGet packages, Ruby gems, Composer packages and |
| 9 | Go modules. Each registry speaks its tool's own protocol, so `docker`, |
| 10 | `npm`, `cargo`, `mvn` and Gradle, `dotnet`, `gem` and Bundler, `composer` |
| 11 | and `go` work with nothing but a login and an address. Composer packages and Go modules are |
| 12 | read from the workspace's repositories: there is nothing to upload. |
| 13 | |
| 14 | | Registry | Address | Guide | |
| 15 | | --- | --- | --- | |
| 16 | | Container images | `g1t.sh/<workspace>/<name>` | [Container images](/guides/containers/) | |
| 17 | | npm | `https://g1t.sh/-/npm/`, for the scope `@<workspace>` | [npm](/guides/npm/) | |
| 18 | | Cargo | `sparse+https://g1t.sh/-/cargo/<workspace>/index/`, a registry per workspace | [Cargo](/guides/cargo/) | |
| 19 | | Maven | `https://g1t.sh/-/maven/<workspace>/`, a repository per workspace, for Maven and Gradle | [Maven](/guides/maven/) | |
| 20 | | NuGet | `https://g1t.sh/-/nuget/<workspace>/v3/index.json`, a feed per workspace, with a symbol server | [NuGet](/guides/nuget/) | |
| 21 | | RubyGems | `https://g1t.sh/-/rubygems/<workspace>/`, a registry per workspace, for `gem push`, `gem install` and Bundler | [RubyGems](/guides/rubygems/) | |
| 22 | | Composer | `https://g1t.sh/-/composer/<workspace>/`, from the workspace's repositories | [Composer](/guides/composer/) | |
| 23 | | Go | `g1t.sh/<workspace>/<repo>`, straight from git | [Go modules](/guides/go/) | |
| 24 | |
| 25 | ## Names |
| 26 | |
| 27 | Every package's name starts with its workspace: `g1t.sh/acme/web` is the |
| 28 | `web` image of the `acme` workspace. A name may have more parts after it, |
| 29 | such as `g1t.sh/acme/web/worker`. |
| 30 | |
| 31 | ## Who can see and publish a package |
| 32 | |
| 33 | Everyone has one role on a package, the highest of what reaches them: |
| 34 | |
| 35 | | Role | Lets them | |
| 36 | | --- | --- | |
| 37 | | Read | Pull and install it. Anyone, signed in or not, may on a public package. | |
| 38 | | Write | Also publish new versions and tags. | |
| 39 | | Admin | Also delete and restore it and its versions, and change its [settings](#package-settings). | |
| 40 | |
| 41 | A package is linked to a repository, or belongs to its workspace, and that |
| 42 | decides where its roles come from: |
| 43 | |
| 44 | - **Linked.** The first push of an image whose name starts with a |
| 45 | repository's name (`acme/web`, `acme/web/worker` for the repository |
| 46 | `acme/web`) links it to that repository, unless its |
| 47 | [source label](/guides/containers/#link-an-image-with-its-source-label) |
| 48 | names another; so does the first publish of an npm package whose |
| 49 | `package.json` `repository` is a g1t.sh repository of the workspace, or |
| 50 | which is named like one (`@acme/web`), and of a crate whose `Cargo.toml` |
| 51 | `repository` is one, or which is named like one. Maven artifacts (by |
| 52 | artifactId, or the POM's `<scm><url>`), NuGet packages (by |
| 53 | `RepositoryUrl`, or their id) and gems (by `source_code_uri`, or their |
| 54 | name) are linked the same way. It has the repository's visibility and, |
| 55 | while it **inherits access** (the default), its |
| 56 | [roles](/guides/access-and-roles/): Read and Triage pull, Write and |
| 57 | Maintain publish, Admin administers. |
| 58 | - **Unlinked.** A package whose name matches no repository is the |
| 59 | workspace's. It is private: members pull and push it by the workspace's |
| 60 | [base permission](/guides/access-and-roles/#the-base-permission) (Read pulls, |
| 61 | Write pushes), and an Admin base permission still only pushes. An admin |
| 62 | can make it public, and then anyone can pull it. |
| 63 | |
| 64 | On top of that: |
| 65 | |
| 66 | - **The workspace's owners** are admins of every package. |
| 67 | - **People and teams given a role on the package itself**, under |
| 68 | [Manage access](#manage-access), have that role, or the one their |
| 69 | repository or base permission gives them if it is higher. A team's role |
| 70 | reaches its child teams' people too. |
| 71 | - **Turning off inheriting** on a linked package leaves only the roles |
| 72 | given on the package itself, and the workspace's owners: the |
| 73 | repository's roles no longer reach it. Its visibility is still the |
| 74 | repository's. |
| 75 | |
| 76 | Private packages look exactly like ones that do not exist to anyone who may |
| 77 | not pull them. |
| 78 | |
| 79 | ## Package settings |
| 80 | |
| 81 | A package's admins see a **Settings** tab on its page, at |
| 82 | `g1t.sh/<workspace>/-/packages/<type>/<name>?tab=settings`: |
| 83 | |
| 84 | | Setting | What it does | |
| 85 | | --- | --- | |
| 86 | | Inherit access from the linked repository | On (the default), the repository's roles reach the package. Off, only the roles below and the workspace's owners do. Linked packages only. | |
| 87 | | Manage access | People (by username) and teams of the workspace (by slug), each with the Read, Write or Admin role on the package. | |
| 88 | | Manage Actions access | The repositories whose workflows may use the package, each with Read or Write. See [below](#manage-actions-access). | |
| 89 | | Visibility | Public or private, for an unlinked package. A linked one has its repository's. | |
| 90 | | Repository | Link it to a repository of its workspace (Admin on that repository is needed too), or unlink it: it is then the workspace's, and private. | |
| 91 | | Deleted versions | Versions deleted in the last 30 days, each with **Restore**. | |
| 92 | | Delete this package | Delete it, with every version. See [deleting and restoring](#delete-and-restore). | |
| 93 | |
| 94 | ### Manage access |
| 95 | |
| 96 | Add a person by username, or a team of the workspace by its slug, with a |
| 97 | role; change a role from its row, or remove it. What a repository or the |
| 98 | workspace gives someone stays when the package's own role is removed. |
| 99 | |
| 100 | ### Manage Actions access |
| 101 | |
| 102 | A workflow job's [`G1T_TOKEN`](/guides/actions/#the-jobs-token) reaches a |
| 103 | package only from these repositories: |
| 104 | |
| 105 | | Repository | Its workflows may | |
| 106 | | --- | --- | |
| 107 | | The one the package is linked to | Pull and publish it, always. It is listed, and cannot be removed: unlink the package instead. | |
| 108 | | One added with Read | Pull it | |
| 109 | | One added with Write | Pull and publish it | |
| 110 | | Any other | Nothing: the job is refused, with a message naming the package and saying to add its repository here. A public package still pulls. | |
| 111 | |
| 112 | A package a workflow job makes that is not linked to the job's repository |
| 113 | (a workspace package, say `g1t.sh/acme/tools` pushed from `acme/web`) is |
| 114 | given its repository with Write, so the workflow that made it keeps |
| 115 | publishing it. The job's token is still held to the job's own |
| 116 | `permissions:`, never deletes a package and never changes its settings. |
| 117 | |
| 118 | ## Delete and restore |
| 119 | |
| 120 | Deleting a package, or one version, hides it from every registry at once: |
| 121 | pulls and installs get "not found", as for one that never existed. It is |
| 122 | kept for **30 days**, and until then: |
| 123 | |
| 124 | - An admin of the package can restore it: a version from the package's |
| 125 | **Settings → Deleted versions**, a package from **Deleted packages** on |
| 126 | the workspace's Packages page (`g1t.sh/<workspace>/-/packages?view=deleted`), |
| 127 | listed for whoever administers it. A restored version comes back with |
| 128 | the tags that still pointed to it. |
| 129 | - A deleted package's name stays taken: nobody can publish a package of |
| 130 | that name in the workspace. A deleted version's version (for a container |
| 131 | image, its digest) cannot be published again. |
| 132 | - Its files are kept, and do not count toward the workspace's storage. |
| 133 | |
| 134 | After 30 days it is purged for good, and files nothing else uses are |
| 135 | removed a day later. Composer versions follow their repository's tags and |
| 136 | branches, so they are deleted there, not here. |
| 137 | |
| 138 | Deleting through a registry's own protocol (`docker` and the OCI `DELETE`, |
| 139 | `npm unpublish`) works the same way. |
| 140 | |
| 141 | ## Tokens |
| 142 | |
| 143 | Sign in to a registry with your username and an |
| 144 | [access token](/guides/authentication/#access-tokens) as the password. |
| 145 | A token with scopes needs the package ones: |
| 146 | |
| 147 | | Scope | Lets a token | |
| 148 | | --- | --- | |
| 149 | | `packages:read` | Pull private packages. Public ones need no scope. | |
| 150 | | `packages:write` | Push and publish. Includes `packages:read`. | |
| 151 | | `packages:delete` | Delete and restore versions and packages | |
| 152 | |
| 153 | Tokens with full access, and tokens made before scopes, have all three. |
| 154 | Changing a package's settings needs `packages:write` and the Admin role on |
| 155 | it. A token never does more than its owner could: `packages:delete` alone |
| 156 | does not let a member delete an owner's package. |
| 157 | |
| 158 | | Token | Reaches | |
| 159 | | --- | --- | |
| 160 | | A personal access token for all your workspaces | What its owner may do, limited by its permissions. | |
| 161 | | A personal access token for one workspace | Packages linked to a repository in its selection, and the unlinked packages of its workspace. Elsewhere it pulls public packages only. | |
| 162 | | A workspace's own token | The workspace's packages, as a member with Write; with Admin when it has Repositories: admin. With selected repositories, linked packages of those only. | |
| 163 | | A workflow job's `G1T_TOKEN` | Its own repository's packages, and those that list its repository under [Manage Actions access](#manage-actions-access), as the job's `permissions:` allow. | |
| 164 | | A deploy key | No packages. | |
| 165 | |
| 166 | In [workflows](/guides/actions/#the-jobs-token), `G1T_TOKEN` is the job's |
| 167 | own token: it pushes and pulls its repository's packages with no setup, and |
| 168 | any other package once its admins add the repository under Manage Actions |
| 169 | access. |
| 170 | |
| 171 | ## Storage |
| 172 | |
| 173 | Every file is kept once, by its content: two images that share a layer |
| 174 | store it once, and a layer pushed again is not stored again. A workspace's |
| 175 | storage counts each file once, as public when any public package uses it. |
| 176 | |
| 177 | Files no version uses any more are deleted a day after the last version |
| 178 | that used them goes. |
| 179 | |
| 180 | Without the [g1t plan](/guides/usage-and-billing/#the-g1t-plan), public |
| 181 | packages may hold 10 GB and private ones 500 MB per workspace; a push past |
| 182 | either is refused, with a message saying how much is used. On the plan, |
| 183 | nothing is refused and storage past those amounts is charged instead: |
| 184 | |
| 185 | - What the workspace's packages hold is measured each day, public and |
| 186 | private apart, each past its own free amount. |
| 187 | - A month's GB-months are those days added up, divided by the days in the month, charged at |
| 188 | $0.018 a GB-month as **Package storage** on the |
| 189 | [bill](/guides/usage-and-billing/). |
| 190 | - Deleted packages and versions, kept for 30 days, do not count. |
| 191 | - Downloads and pulls cost nothing. Anonymous pulls are rate limited; see |
| 192 | [storage and pull limits](/guides/containers/#storage-and-pull-limits). |
| 193 | |
| 194 | ## Downloads |
| 195 | |
| 196 | Each package's page shows its pulls or downloads, and each version's own, |
| 197 | counted approximately: an image's manifest fetched by tag or digest, an npm |
| 198 | tarball, a crate, a Maven artifact (not its POM or signatures), a NuGet |
| 199 | `.nupkg`, a gem, and a Composer zip. |
| 200 | |
| 201 | A package's files are its publisher's, so the registries never let a |
| 202 | browser run them. Every registry answer carries |
| 203 | `X-Content-Type-Options: nosniff` and |
| 204 | `Content-Security-Policy: default-src 'none'; sandbox`, and a file a |
| 205 | browser would open as a page, such as a POM, a `.nuspec` or anything else |
| 206 | in XML, HTML or SVG, comes with `Content-Disposition: attachment`, so it |
| 207 | downloads instead. Package managers ignore these headers. |
| 208 | |
| 209 | ## The API |
| 210 | |
| 211 | The [REST API](/reference/api/) and the `package` tool of the |
| 212 | [MCP server](/reference/mcp/) manage packages. A package is named by its |
| 213 | type (`container`, `npm`, `cargo`, `maven`, `nuget`, `rubygems` or |
| 214 | `composer`) and its name, URL-encoded where it holds a slash |
| 215 | (`web%2Fworker`): |
| 216 | |
| 217 | | Route | Operation | Scope | |
| 218 | | --- | --- | --- | |
| 219 | | `GET /workspaces/{workspace}/packages` | `list_packages` (`state=deleted` for deleted ones) | `packages:read` | |
| 220 | | `GET /workspaces/{workspace}/packages/{package_type}/{package_name}` | `get_package` | `packages:read` | |
| 221 | | `PATCH …/{package_name}` | `update_package`: `visibility`, `inherit_access` | `packages:write` | |
| 222 | | `DELETE …/{package_name}` | `delete_package` | `packages:delete` | |
| 223 | | `POST …/{package_name}/restore` | `restore_package` | `packages:delete` | |
| 224 | | `GET …/{package_name}/versions` | `list_package_versions` (`state=deleted` for deleted ones) | `packages:read` | |
| 225 | | `GET …/versions/{version_id}` | `get_package_version` | `packages:read` | |
| 226 | | `DELETE …/versions/{version_id}` | `delete_package_version` | `packages:delete` | |
| 227 | | `POST …/versions/{version_id}/restore` | `restore_package_version` | `packages:delete` | |
| 228 | | `PUT …/{package_name}/repository` | `link_package` | `packages:write` | |
| 229 | | `DELETE …/{package_name}/repository` | `unlink_package` | `packages:write` | |
| 230 | | `GET …/{package_name}/access` | `list_package_access` | `packages:read` | |
| 231 | | `PUT …/{package_name}/access` | `set_package_access`: `username` or `team`, and `role` | `packages:write` | |
| 232 | | `DELETE …/{package_name}/access?username=…` or `?team=…` | `remove_package_access` | `packages:write` | |
| 233 | | `GET …/{package_name}/actions-access` | `list_package_actions_access` | `packages:read` | |
| 234 | | `PUT …/{package_name}/actions-access` | `set_package_actions_access`: `repository` and `role` | `packages:write` | |
| 235 | | `DELETE …/{package_name}/actions-access/{repository}` | `remove_package_actions_access` | `packages:write` | |
| 236 | |
| 237 | `version_id` is a version's id (`ver_…`), its version, its digest, or a tag |
| 238 | that points to it. Reading access and deleted versions, and every change, |
| 239 | also needs the Admin role on the package. Bodies and answers are |
| 240 | snake_case. |
| 241 | |
| 242 | ## Events and the audit log |
| 243 | |
| 244 | Publishing a version, deleting a version and deleting a package are |
| 245 | [audit log](/guides/audit-log/) entries (so are deprecating an npm version, |
| 246 | yanking or unyanking a crate version, unlisting or listing a NuGet version, |
| 247 | pushing a NuGet version's symbols and yanking a gem version), as are |
| 248 | restoring them, purging them after 30 days, every change to who has access |
| 249 | and to Manage Actions access, changing the visibility, and linking and |
| 250 | unlinking (see the [audit log's list](/guides/audit-log/)). |
| 251 | |
| 252 | [Webhooks](/guides/webhooks/) can subscribe to these events. A linked |
| 253 | package's go to its repository's webhooks and its workspace's; an |
| 254 | unlinked package's go to its workspace's webhooks. |
| 255 | |
| 256 | | Event | Sent when | |
| 257 | | --- | --- | |
| 258 | | `package.published` | A version is published. `data.tags` names the tags that now point to it. | |
| 259 | | `package.version_deleted` | A version is deleted. | |
| 260 | | `package.deleted` | A package is deleted. | |
| 261 | | `package.visibility_changed` | A package is made public or private. `data.visibility` is the new one. | |
| 262 | |
| 263 | Each one's `data` has `package_id`, `workspace`, `ecosystem`, `name` and |
| 264 | `repo_id` (null for an unlinked package); a version's event also has its |
| 265 | `version` and `digest` (for a container image, the manifest's), and |
| 266 | `package.published` its `size`, except for a Composer package. |
| 267 | |
| 268 | ## Not supported yet |
| 269 | |
| 270 | - PyPI packages. |
| 271 | - Installing unscoped npm packages, or other scopes, through g1t.sh, and |
| 272 | a copy of Packagist for Composer: those still come from their public |
| 273 | registries. |
| 274 | - A Go module proxy: Go modules are fetched with git. |
| 275 | - Workflows that run when a package is published. |
| 276 | - Packages in site-wide search. |