Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Recognized types:
- `custom_files`

Notes:
- `registry` is used as a target for image push operations.
- `registry` can be used as a **sync source** (enumerating repositories/tags and pulling manifests+blobs from a registry) and/or as a **push target** for `airgap registry push`.
- `custom_files` is accepted as config type but not wired as a sync provider yet.

## Code Change Expectations
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to this project are documented in this file.

## 0.4.0 - 2026-02-26

### Added

- **Registry as sync source**: the `registry` provider type can now act as a sync source, enumerating repository tags via the Docker Registry V2 API and downloading manifests/blobs locally. Configure with `repositories`, `tags` (glob filters), and `output_dir` fields.
- Registry provider UI form updated with sync source sections (repositories, tag filters, output directory) alongside existing push target fields.
- Sync history table on provider detail page showing the last 10 sync runs with duration, status, and transfer stats.
- Dashboard empty state with "Get Started" prompt when no providers are configured.
- Dynamic version display in sidebar (uses build-time `version` variable instead of hardcoded value).

## 0.3.5 - 2026-02-24

### Changed
Expand Down
5 changes: 4 additions & 1 deletion cmd/airgap/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/BadgerOps/airgap/internal/provider/containerimages"
"github.com/BadgerOps/airgap/internal/provider/epel"
"github.com/BadgerOps/airgap/internal/provider/ocp"
registryprovider "github.com/BadgerOps/airgap/internal/provider/registry"
"github.com/BadgerOps/airgap/internal/store"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -159,7 +160,9 @@ func createProvider(typeName, dataDir string, log *slog.Logger) (provider.Provid
return ocp.NewRHCOSProvider(dataDir, log), nil
case "container_images":
return containerimages.NewProvider(dataDir, log), nil
case "registry", "custom_files":
case "registry":
return registryprovider.NewProvider(dataDir, log), nil
case "custom_files":
return nil, fmt.Errorf("provider type %q is not yet implemented", typeName)
default:
return nil, fmt.Errorf("unknown provider type: %q", typeName)
Expand Down
1 change: 1 addition & 0 deletions cmd/airgap/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func serveRun(cmd *cobra.Command, args []string) error {

// Create the HTTP server
srv := server.NewServer(globalEngine, globalRegistry, globalStore, globalCfg, logger)
srv.SetVersion(version)

// Channel to listen for errors from server
errChan := make(chan error, 1)
Expand Down
27 changes: 17 additions & 10 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,24 @@ type ContainerImagesProviderConfig struct {
OutputDir string `yaml:"output_dir"`
}

// RegistryProviderConfig is the typed config for mirror-registry
// RegistryProviderConfig is the typed config for mirror-registry.
// When Repositories is non-empty the provider acts as a sync source,
// enumerating tags via the Docker Registry V2 API and downloading
// manifests/blobs locally. When Repositories is empty it is a push-only
// target used by `airgap registry push`.
type RegistryProviderConfig struct {
Enabled bool `yaml:"enabled"`
MirrorRegistryBinary string `yaml:"mirror_registry_binary"`
QuayRoot string `yaml:"quay_root"`
Endpoint string `yaml:"endpoint"`
RepositoryPrefix string `yaml:"repository_prefix"`
Username string `yaml:"username"`
Password string `yaml:"password"`
InsecureSkipTLS bool `yaml:"insecure_skip_tls"`
SkopeoBinary string `yaml:"skopeo_binary"`
Enabled bool `yaml:"enabled"`
MirrorRegistryBinary string `yaml:"mirror_registry_binary"`
QuayRoot string `yaml:"quay_root"`
Endpoint string `yaml:"endpoint"`
RepositoryPrefix string `yaml:"repository_prefix"`
Username string `yaml:"username"`
Password string `yaml:"password"`
InsecureSkipTLS bool `yaml:"insecure_skip_tls"`
SkopeoBinary string `yaml:"skopeo_binary"`
Repositories []string `yaml:"repositories"`
Tags []string `yaml:"tags"`
OutputDir string `yaml:"output_dir"`
}

// CustomFilesProviderConfig is the typed config for custom file sources
Expand Down
Loading