{"id":44092411,"url":"https://github.com/jfrog/fly-action","last_synced_at":"2026-05-28T12:01:02.703Z","repository":{"id":320080915,"uuid":"979257755","full_name":"jfrog/fly-action","owner":"jfrog","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-06T08:45:50.000Z","size":241934,"stargazers_count":7,"open_issues_count":4,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-06T09:41:33.864Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jfrog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-07T08:32:22.000Z","updated_at":"2026-05-02T08:13:33.000Z","dependencies_parsed_at":"2025-10-21T21:38:54.168Z","dependency_job_id":"70b1421f-1de4-4169-bfe7-63974e02f33f","html_url":"https://github.com/jfrog/fly-action","commit_stats":null,"previous_names":["jfrog/fly-action"],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/jfrog/fly-action","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfrog%2Ffly-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfrog%2Ffly-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfrog%2Ffly-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfrog%2Ffly-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jfrog","download_url":"https://codeload.github.com/jfrog/fly-action/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jfrog%2Ffly-action/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33607334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-08T11:15:06.656Z","updated_at":"2026-05-28T12:01:02.695Z","avatar_url":"https://github.com/jfrog.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Fly Action\n\n[![Scanned by Frogbot](https://raw.githubusercontent.com/jfrog/frogbot/refs/heads/master/images/frogbot-badge.svg)](https://docs.jfrog-applications.jfrog.io/jfrog-applications/frogbot)\n[![docs](https://img.shields.io/badge/Docs-%F0%9F%93%96-blue)](https://docs.fly.jfrog.com)\n\n\u003c/div\u003e\n\nThis GitHub Action downloads the Fly CLI and configures package managers to use Fly as a registry for dependencies.\n\n## What is JFrog Fly?\n\nJFrog Fly is a release management platform for software teams. Every build your\nCI produces becomes a tracked release — linked to its commits, PRs, and artifacts,\nsearchable by content from your IDE and available for your coding agents.\n\n\u003e **Not affiliated with Fly.io** (the application deployment platform).\n\n**From your coding agent you can:**\n- Find any release by what it contains: *\"Find the release that fixed the login bug\"*\n- Configure CI end-to-end: *\"Start working with Fly\"*\n- Deploy to Kubernetes: *\"Deploy the latest staging release to production\"*\n- Track what's running: *\"Is the login fix live in production?\"*\n\nWorks with Cursor, Claude Code, VS Code (Copilot), and OpenCode.\n\n## Install JFrog Fly\n\nFly Desktop installs in seconds and automatically configures your coding agent\nand package managers.\n\n**macOS / Linux**\n```bash\ncurl -fsSL https://fly.jfrog.ai/download/desktop | bash\n```\n\n**Windows**\n```powershell\npowershell -c \"irm https://fly.jfrog.ai/download/desktop | iex\"\n```\n\nThe app opens and walks you through sign-up. Once installed, open your IDE and ask:\n\n```\nStart working with Fly\n```\n\nYour agent connects your GitHub repo, configures CI authentication, and opens a\nverified PR — no manual steps.\n\n→ [Full getting-started guide](https://docs.fly.jfrog.com/getting-started/)\n\n---\n\n## Features\n\n- ✅ Zero-configuration — tenant resolved automatically from GitHub OIDC token\n- ✅ Supports all package managers available in Fly CLI\n- ✅ Configures all detected package managers with a single command\n- ✅ Upload and download generic artifacts via sub-actions (`[LATEST]` resolves on both authenticated and public paths — fly-service resolves it server-side via AQL on the auth path, 302 redirect on the public path)\n- ✅ Distribute generic artifacts publicly via sub-action — share with anyone, no Fly account required\n- ✅ Publish Go modules to Fly Go registry\n- ✅ OIDC authentication only\n- ✅ Allows ignoring specific package managers\n- ✅ Automatic CI session end notification to the Fly server\n- ✅ Retry mechanism with exponential backoff for CI notifications\n- ✅ Exports tenant registry hostname as `FLY_REGISTRY_SUBDOMAIN` environment variable for subsequent steps\n- ✅ Job summary with collected artifacts and transfer results\n\n## Quick Start\n\n```yaml\nname: Build with Fly Registry\non: [push]\n\npermissions:\n  contents: read\n  id-token: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      \n      # Setup Fly registry — tenant is resolved automatically from OIDC\n      - name: Setup Fly Registry\n        uses: jfrog/fly-action@v1\n\n      # FLY_REGISTRY_SUBDOMAIN is now available for Docker, Helm, or any registry operation\n      - name: Build and push Docker image\n        run: |\n          docker build -t ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:${{ github.sha }} .\n          docker push ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:${{ github.sha }}\n```\n\n## Generic Artifact Sub-Actions\n\nTransfer and publish generic artifacts (binaries, archives, build outputs) using dedicated sub-actions: `upload`, `download`, and `distribute`.\n\n### Upload\n\n```yaml\n- name: Upload build artifacts\n  uses: jfrog/fly-action/upload@v1\n  with:\n    name: my-app\n    version: '1.0.0'\n    files: |\n      dist/app.zip\n      dist/app.tar.gz\n      dist/**\n    exclude: |\n      *.log\n```\n\n| Input | Description | Required | Default |\n| --- | --- | --- | --- |\n| `name` | Package name | Yes | |\n| `version` | Package version | Yes | |\n| `files` | Files to upload — one per line, supports glob patterns | Yes | |\n| `exclude` | Glob patterns to exclude — one per line | No | |\n| `if-no-files-found` | Behavior when the `files` glob matches nothing after applying excludes. One of `error` (fail the step), `warn` (log a warning, continue), `ignore` (silent no-op). | No | `error` |\n\nGlob patterns are expanded by the Fly CLI and support recursive matches such as `dist/**`.\nPatterns like `dist/**` upload regular files under `dist` recursively.\nDirectories and symlinks are not uploaded, and symlinked directories are not traversed.\nFiles are uploaded flat using their basename, so `dist/linux/app.tar.gz` is stored as `app.tar.gz`.\n\n#### Zero-match glob handling\n\nBy default, `files` patterns that match nothing fail the step (`error`). For optional artifacts — for example, a build that may or may not produce a debug bundle — set `if-no-files-found` to `warn` (log + continue) or `ignore` (silent no-op):\n\n```yaml\n- name: Upload optional debug bundle\n  uses: jfrog/fly-action/upload@v1\n  with:\n    name: my-app\n    version: '1.0.0'\n    files: |\n      dist/debug-*.zip\n    if-no-files-found: warn\n```\n\nThe action validates the value before invoking the Fly CLI. Anything other than `error` / `warn` / `ignore` (case-sensitive) fails the step with an explicit message.\n\n### Download\n\n```yaml\n- name: Download a specific version\n  uses: jfrog/fly-action/download@v1\n  with:\n    name: my-app\n    version: '1.0.0'\n    files: |\n      app.zip\n    output-dir: ./downloads\n\n- name: Download the latest version (omit version)\n  uses: jfrog/fly-action/download@v1\n  with:\n    name: my-app\n    files: |\n      app.zip\n    output-dir: ./downloads\n```\n\n| Input | Description | Required | Default |\n| --- | --- | --- | --- |\n| `name` | Package name | Yes | |\n| `version` | Package version. Omit to fetch the latest. | No | `[LATEST]` |\n| `files` | Remote filenames to download — one per line | Yes | |\n| `output-dir` | Directory to save downloaded files | No | `.` |\n| `exclude` | Glob patterns to exclude — one per line | No | |\n\n#### `[LATEST]` resolution\n\n`[LATEST]` is the case-insensitive sentinel for \"the most recently published version\" (`[LATEST]`, `[latest]`, `[Latest]` all accepted). Where it resolves depends on the path:\n\n| Path | `[LATEST]` resolved? | How |\n|---|---|---|\n| **Public URL** — `https://{tenant}.jfrog.io/public/generic/{name}/[LATEST]/{file}` (after a `distribute` step) | Yes (today) | `fly-service` returns `302 Found` + `Location: …/{concrete}/{file}` + `Cache-Control: no-store`. The redirect is never CDN-cached, so changes to \"latest\" are visible immediately; the concrete URL it redirects to is independently cacheable as immutable artifact data. |\n| **Authenticated** — `download` sub-action (this is what the action invokes via the Fly CLI) | Yes | fly-service resolves `[LATEST]` server-side via AQL (most recently created version wins) and proxies the file inline with `Cache-Control: no-store` — no redirect is issued. Inline proxying lets fly-service intercept Artifactory 404s and return a Fly-owned message naming the resolved version, so CI workflows can spot upload gaps. The job summary shows the literal `[LATEST]` token rather than the concrete version (display-only limitation; download correctness is unaffected). |\n\nThe action defaults `version` to `[LATEST]` for `download` so workflows that omit the version automatically get the latest build.\n\nUse `[LATEST]` for \"give me whatever the most recent build is\" workflows (consumers in another repo). Pin a concrete version when you need reproducibility (debugging an old release, regression testing).\n\n`[LATEST]` is **download-only**. The Fly server rejects it with `400 Bad Request` on `upload` (PUT/POST) and `distribute` so a literal `[LATEST]`-named folder can never poison future resolution.\n\n### Distribute\n\nMake an artifact version publicly downloadable — anyone with the link can grab it without a Fly account. Idempotent: calling again returns the same public URL. Supported package types: **generic**, **docker**.\n\n#### Generic\n\n```yaml\n- name: Distribute the artifact\n  uses: jfrog/fly-action/distribute@v1\n  with:\n    name: my-app\n    version: '1.0.0'\n```\n\nAfter distribute succeeds, consumers fetch the file anonymously:\n\n```bash\n# Specific version\ncurl -O https://{tenant}.jfrog.io/public/generic/my-app/1.0.0/app.zip\n\n# Latest version (server 302-redirects to the newest distributed version)\ncurl -LO https://{tenant}.jfrog.io/public/generic/my-app/[LATEST]/app.zip\n```\n\nThe generic public URL pattern is `https://{tenant}.jfrog.io/public/generic/{name}/{version}/{file}`.\n\n#### Docker\n\nThe image must already have been pushed to the tenant's `docker-local` repo (via `docker push {tenant}.jfrog.io/docker/...` after `jfrog/fly-action` configured the registry). The distribute step copies the manifest and layer blobs into the `{tenant}-docker-public` repo so anonymous pulls can resolve them.\n\n```yaml\n- name: Distribute the docker image\n  uses: jfrog/fly-action/distribute@v1\n  with:\n    name: myorg/my-image      # image name without registry host or `docker-public/` prefix\n    version: '1.0.0'          # image tag\n    type: docker\n```\n\nAfter distribute succeeds, consumers pull the image anonymously:\n\n```bash\n# Specific tag\ndocker pull {tenant}.jfrog.io/docker-public/myorg/my-image:1.0.0\n\n# Latest tag (server 302-redirects to the newest distributed tag)\ndocker pull {tenant}.jfrog.io/docker-public/myorg/my-image:[LATEST]\n```\n\nThe docker public URL pattern is `https://{tenant}.jfrog.io/v2/docker-public/{image}/manifests/{tag}` (OCI registry API). The `/v2/docker-public/*` namespace is read-only — pushes always go through the authenticated distribute step above, never anonymously.\n\n#### Distribute inputs\n\n| Input | Description | Required | Default |\n| --- | --- | --- | --- |\n| `name` | Package name (for docker, the image name without the registry host or `docker-public/` prefix; nested repos like `myorg/myimg` are supported) | Yes | |\n| `version` | Package version to make public (for docker, the image tag). Concrete only — `[LATEST]` is not accepted here. | Yes | |\n| `type` | Artifact type. Supported values: `generic`, `docker`. | No | `generic` |\n\n#### `[LATEST]` on the public path\n\n`[LATEST]` is resolved server-side on **both** public URL shapes (generic `/public/generic/...` and docker `/v2/docker-public/...`) via `302 Found` + `Cache-Control: no-store`, so consumers always see the latest distributed version and the CDN never pins a stale resolution. The authenticated `download` sub-action also resolves `[LATEST]` — via inline proxy, no redirect — see [`[LATEST]` resolution](#latest-resolution) above.\n\n`[LATEST]` is **download-only**. The Fly server rejects it with `400 Bad Request` on `distribute` (and `upload`) so a literal `[LATEST]`-named folder or tag can never poison future resolution.\n\n#### Distribute outputs\n\nThe `results` output is a JSON array with one entry: `{package_name, package_version, package_type, public_url, download_url, download_count, files?}`. Docker distributions also surface a `Pull:` line in the step logs with the ready-to-paste `docker pull …` command. Multiple distribute steps in one job accumulate in the job summary's _Distributed Artifacts_ table.\n\n### Go Publish\n\nPublish Go modules to the Fly Go registry.\n\n```yaml\n- name: Publish Go module\n  uses: jfrog/fly-action/go-publish@v1\n  with:\n    path: ./libs/mylib   # optional — defaults to repository root\n    version: v1.2.3      # optional — auto-detected from git tags if omitted\n```\n\n| Input | Description | Required | Default |\n| --- | --- | --- | --- |\n| `path` | Path to the module directory containing `go.mod` | No | `.` |\n| `version` | Module version to publish | No | Auto-detected from git tags |\n\n\u003e **Note**: Consumers of modules published to Fly need to configure Go to skip the public checksum database, since privately published modules are not registered on `sum.golang.org`:\n\u003e\n\u003e ```bash\n\u003e go env -w GONOSUMDB=example.com/myorg/* GONOSUMCHECK=example.com/myorg/*\n\u003e ```\n\u003e\n\u003e Replace `example.com/myorg` with your module path prefix (typically the first two segments of the module path).\n\nAll three generic sub-actions (`upload`, `download`, `distribute`) output a `results` JSON array — per-file status for upload/download, and a single distributed-artifact entry for distribute:\n\n```yaml\n- name: Upload\n  id: upload\n  uses: jfrog/fly-action/upload@v1\n  with:\n    name: my-app\n    version: '1.0.0'\n    files: dist/app.zip\n\n- name: Check results\n  run: echo '${{ steps.upload.outputs.results }}'\n```\n\n## OIDC Authentication (Required)\n\nThis action requires OIDC authentication. The OIDC token is used to track uploads and downloads on the Fly server. You must set `permissions: id-token: write` in your workflow file.\n\n```yaml\npermissions:\n  contents: read\n  id-token: write # Required for OIDC authentication\n```\n\nWhen using OIDC authentication:\n\n1. You need to set `permissions: id-token: write` in your workflow file\n2. The action will:\n   - Request an OIDC token from GitHub Actions\n   - Resolve the Fly tenant automatically from the OIDC token's `repository_owner_id` claim\n   - Exchange it for a Fly access token\n   - Use the resulting token to authenticate with Fly\n   - Automatically notify the Fly server when the CI session ends (using GitHub Actions post-job mechanism)\n\n\u003e **Note**: The CI end notification runs automatically as a post-job step. This ensures it executes even if the main action fails, for proper session management on the Fly server. If the CI end notification step itself encounters an error, it will cause the overall workflow to be marked as failed.\n\n## Inputs\n\n| Input | Description | Required | Default |\n| --- | --- | --- | --- |\n| `ignore` | Comma-separated list of package managers to ignore | No | None |\n\n## Environment Variables\n\nAfter the action runs, the following environment variables are available in all subsequent steps:\n\n| Variable | Description |\n| --- | --- |\n| `FLY_REGISTRY_SUBDOMAIN` | Resolved tenant registry hostname (e.g., `acmecorp.jfrog.io`). Use for Docker image tags, Helm OCI refs, etc. |\n| `FLY_URL` | Full Fly tenant URL (e.g., `https://acmecorp.jfrog.io`). Used by the fly CLI and sub-actions. |\n| `FLY_ACCESS_TOKEN` | Short-lived OIDC-derived access token. Used by the fly CLI and sub-actions. Masked in logs via `core.setSecret`. |\n\n```yaml\n- name: Push Docker image\n  run: docker push ${{ env.FLY_REGISTRY_SUBDOMAIN }}/docker/my-app:latest\n\n- name: Push Helm chart\n  run: helm push mychart-1.0.0.tgz oci://${{ env.FLY_REGISTRY_SUBDOMAIN }}/helmoci\n\n- name: Use fly CLI directly\n  run: fly upload --name my-pkg --version 1.0.0 ./artifact.zip\n```\n\n### Trust Model\n\n`FLY_ACCESS_TOKEN` is exported to `GITHUB_ENV` so that sub-actions and `run:` steps can use the fly CLI. This means **any subsequent step in the job** (including third-party actions) can read the token via `process.env`. The token is:\n\n- **Short-lived** — scoped to the CI session, expires when the job ends\n- **Masked in logs** — registered via `core.setSecret` so it won't appear in action output\n- **OIDC-scoped** — derived from the repository's OIDC claims, limited to the tenant\n\nIf you use third-party actions after `jfrog/fly-action`, ensure you trust them with this access level.\n\n## GitHub Enterprise Server (GHES)\n\nOn GitHub Enterprise Server, the default `fly.jfrog.ai` endpoint cannot resolve tenants because GHES installations live in a separate Fly environment.\n\nSet the `CUSTOM_FLY_URL` organization-level variable to your Fly environment URL:\n\n```yaml\nenv:\n  CUSTOM_FLY_URL: https://fly.your-instance.jfrog.info\n\njobs:\n  build:\n    runs-on: self-hosted\n    steps:\n      - uses: jfrog/fly-action@v1\n```\n\nThe action enforces HTTPS on all custom URLs to prevent OIDC token exfiltration.\n\n## Supported Package Managers\n\nThe action supports all package managers that the Fly CLI supports:\n\n- **npm, pnpm, yarn** – Node.js package managers (npm registry)\n- **pip, pipenv, poetry, twine, uv** – Python package managers (PyPI repository)\n- **nuget, dotnet** – .NET package managers (NuGet)\n- **docker, podman** – Container registries (Docker)\n- **helm** – Kubernetes package manager\n- **go** – Go modules\n- **gradle** – Gradle build tool\n- **maven** – Maven build tool\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for information on development setup, testing, and publishing.\n\n## License\n\nThis GitHub Action is licensed under the [Apache-2.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjfrog%2Ffly-action","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjfrog%2Ffly-action","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjfrog%2Ffly-action/lists"}