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
7 changes: 7 additions & 0 deletions README-es.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,12 @@ El binario de RoadRunner construido incluirá solo los plugins especificados en
<repository type="gitlab" uri="path/to/my/repository" asset-pattern="/^cool-.*/" />
<binary name="cool" pattern="/^cool-.*/" />
</software>

<!-- Monorepo con tags de release-please como `cli-v1.2.0` -->
<software name="my-cli" description="Componente CLI de un monorepo">
<repository type="github" uri="my-org/monorepo" tag-prefix="cli-" asset-pattern="/^cli-.*/" />
<binary name="cli" pattern="/^cli-.*/" />
</software>
</registry>
</dload>
```
Expand All @@ -571,6 +577,7 @@ El binario de RoadRunner construido incluirá solo los plugins especificados en
- **type**: Actualmente soporta "github"
- **uri**: Ruta del repositorio (ej., "username/repo")
- **asset-pattern**: Patrón regex para hacer match con assets de release
- **tag-prefix**: Texto antes de la versión en los tags de release, p. ej. `bun-` para `bun-v1.4.2`. Los releases con otros tags se ignoran, así que de un monorepo con tags por componente (release-please) solo se usa el componente seleccionado

#### Elementos Binary

Expand Down
7 changes: 7 additions & 0 deletions README-ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,12 @@ DLoad автоматически управляет процессом сбор
<repository type="gitlab" uri="path/to/my/repository" asset-pattern="/^cool-.*/" />
<binary name="cool" pattern="/^cool-.*/" />
</software>

<!-- Монорепозиторий с тегами release-please вида `cli-v1.2.0` -->
<software name="my-cli" description="CLI-компонент монорепозитория">
<repository type="github" uri="my-org/monorepo" tag-prefix="cli-" asset-pattern="/^cli-.*/" />
<binary name="cli" pattern="/^cli-.*/" />
</software>
</registry>
</dload>
```
Expand All @@ -573,6 +579,7 @@ DLoad автоматически управляет процессом сбор
- **type**: В настоящее время поддерживает "github"
- **uri**: Путь репозитория (например, "username/repo")
- **asset-pattern**: Regex-паттерн для соответствия ресурсам релиза
- **tag-prefix**: Текст перед версией в тегах релизов, например `bun-` для `bun-v1.4.2`. Релизы с другими тегами игнорируются, поэтому из монорепозитория с тегами по компонентам (release-please) берётся только нужный компонент

#### Элементы Binary

Expand Down
7 changes: 7 additions & 0 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,12 @@ DLoad 会自动处理构建过程:
<repository type="gitlab" uri="path/to/my/repository" asset-pattern="/^cool-.*/" />
<binary name="cool" pattern="/^cool-.*/" />
</software>

<!-- 使用 release-please 标签(如 `cli-v1.2.0`)的 monorepo -->
<software name="my-cli" description="monorepo 中的 CLI 组件">
<repository type="github" uri="my-org/monorepo" tag-prefix="cli-" asset-pattern="/^cli-.*/" />
<binary name="cli" pattern="/^cli-.*/" />
</software>
</registry>
</dload>
```
Expand All @@ -564,6 +570,7 @@ DLoad 会自动处理构建过程:
- **type**:目前支持 "github"
- **uri**:仓库路径(例如 "username/repo")
- **asset-pattern**:匹配发布资源的正则表达式模式
- **tag-prefix**:发布标签中版本号之前的文本,例如 `bun-v1.4.2` 中的 `bun-`。标签不以它开头的发布会被忽略,因此对于按组件打标签的 monorepo(release-please),只会使用选定的组件

#### 二进制要素

Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,12 @@ This ensures consistent Velox versions across different environments and team me
<repository type="gitlab" uri="path/to/my/repository" asset-pattern="/^cool-.*/" />
<binary name="cool" pattern="/^cool-.*/" />
</software>

<!-- Monorepo with release-please tags like `cli-v1.2.0` -->
<software name="my-cli" description="CLI component of a monorepo">
<repository type="github" uri="my-org/monorepo" tag-prefix="cli-" asset-pattern="/^cli-.*/" />
<binary name="cli" pattern="/^cli-.*/" />
</software>
</registry>
</dload>
```
Expand All @@ -577,6 +583,7 @@ This ensures consistent Velox versions across different environments and team me
- **type**: Currently supports "github"
- **uri**: Repository path (e.g., "username/repo")
- **asset-pattern**: Regex pattern to match release assets
- **tag-prefix**: Text before the version in release tags, e.g. `bun-` for `bun-v1.4.2`. Releases with other tags are ignored, so only the selected component of a monorepo with per-component tags (release-please) is used

#### Binary Elements

Expand Down
5 changes: 5 additions & 0 deletions dload.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@
<xs:documentation>Regular expression pattern to match assets</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="tag-prefix" type="xs:string">
<xs:annotation>
<xs:documentation>Text before the version in release tags, like "bun-" in "bun-v1.4.2". Releases whose tag does not start with it are ignored, which selects one component of a monorepo (release-please style tags).</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="binary" minOccurs="0" maxOccurs="unbounded">
Expand Down
18 changes: 18 additions & 0 deletions resources/software.json
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,24 @@
"name": "deno",
"version-command": "--version"
}
},
{
"name": "Bun",
"alias": "bun",
"description": "Incredibly fast JavaScript runtime, bundler, test runner, and package manager - all in one.",
"homepage": "https://bun.com",
"repositories": [
{
"type": "github",
"uri": "oven-sh/bun",
"tag-prefix": "bun-",
"asset-pattern": "/^bun-[a-z]+-(?:x64|aarch64)\\.zip$/"
}
],
"binary": {
"name": "bun",
"version-command": "--version"
}
}
]
}
4 changes: 4 additions & 0 deletions resources/software.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
"asset-pattern": {
"type": "string",
"description": "Regular expression pattern to match assets"
},
"tag-prefix": {
"type": "string",
"description": "Text before the version in release tags, like `bun-` in `bun-v1.4.2`. Releases whose tag does not start with it are ignored, which selects one component of a monorepo (release-please style tags)."
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion skills/dload-fetch-tool/references/registry-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ How to describe a tool dload does not ship, as a `<software>` block inside `<reg
## Facts to collect

1. **GitHub repo** as `owner/repo`.
2. **A real release tag** to inspect — any recent one.
2. **A real release tag** to inspect — any recent one. Note any text before the version (`bun-v1.4.2`, `cli-v2.0.0`): it needs a [`tag-prefix`](#tag-prefix).
3. **The asset filename matrix**:
```bash
curl -s https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag> \
Expand Down Expand Up @@ -38,6 +38,12 @@ Tokens the OS/arch matchers recognise (case-insensitive, bounded by `_` or a wor

Patterns are slash-delimited, and in XML attributes backslashes are literal — write `\.exe`.

## `tag-prefix`

A literal string the release tags start with, cut off before the version is parsed. dload reads the version from the tag, so a tag like `bun-v1.4.2` is skipped as unparsable until `tag-prefix="bun-"` is set.

It also selects one component of a monorepo with per-component tags (release-please: `cli-v2.0.0`, `sdk-v1.4.0`): releases whose tag does not start with the prefix are ignored. Include the separator in the prefix (`cli-`, `cli/`), leave the `v` out — it is part of the version.

## `binary.pattern`

Matches the **executable on disk after the asset is downloaded and extracted**:
Expand Down
1 change: 1 addition & 0 deletions skills/dload-fetch-tool/references/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ curl -s "https://api.github.com/repos/<owner>/<repo>/releases?per_page=20" \

- `prerelease: true` while `version` demands stable → lower the stability (`@beta`/`@RC`/`@alpha`).
- `draft: true` → invisible to dload until published.
- Tags carry text before the version (`bun-v1.4.2`, `cli-v2.0.0`) → set `tag-prefix` on the `<repository>`; without it the tags do not parse and every release is skipped. See [`registry-entry.md`](registry-entry.md#tag-prefix).
- Tag is on GitHub but dload picks an older one → the version registry still holds a fresh check; rerun with `dload get --refresh`. A release inserted below the top of the listing (e.g. a GitLab release with a backdated date) needs `dload cache:clear <alias>`. See [`version-registry.md`](version-registry.md).
- API errors (HTTP 401, 403, rate limit) → set a valid `GITHUB_TOKEN` / `GITLAB_TOKEN`. When a check fails but the registry already holds releases of the repository, dload serves the stored ones (a rate limit is reported as "newer ones may be missing"); a never-seen repository fails outright.

Expand Down
12 changes: 11 additions & 1 deletion src/Module/Config/Schema/Embed/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
* @psalm-type RepositoryArray = array{
* type: non-empty-string,
* uri: non-empty-string,
* asset-pattern?: non-empty-string
* asset-pattern?: non-empty-string,
* tag-prefix?: string
* }
*/
#[InflectableConfig]
Expand All @@ -41,6 +42,14 @@ final class Repository
#[XPath('@asset-pattern')]
public string $assetPattern = '/^.*$/';

/**
* @var string $tagPrefix Text before the version in release tags, like `bun-` in `bun-v1.4.2`.
* Releases whose tag does not start with it are ignored, which selects one component
* in a monorepo with per-component tags (release-please style).
*/
#[XPath('@tag-prefix')]
public string $tagPrefix = '';

/**
* Creates a Repository configuration from an array.
*
Expand All @@ -52,6 +61,7 @@ public static function fromArray(mixed $repositoryArray): self
$self->type = $repositoryArray['type'] ?? 'github';
$self->uri = $repositoryArray['uri'];
$self->assetPattern = $repositoryArray['asset-pattern'] ?? '/^.*$/';
$self->tagPrefix = $repositoryArray['tag-prefix'] ?? '';

return $self;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Module/Downloader/Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,7 @@ private function processRepository(Repository $repository, DownloadContext $cont
return $context->release;
} catch (ReleaseGone $e) {
// The registry must not offer this release again, and the list needs a fresh check
$tag = $context->release->getVersion()->string;
$tag === '' or $this->registry->forget($context->repositoryId, $tag);
$this->registry->forget($context->repositoryId, $context->release->getTag());
$forgotten = true;

$context->releaseAttempt->reason ??= $e->getMessage();
Expand Down
2 changes: 1 addition & 1 deletion src/Module/Repository/Internal/GitHub/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function create(RepositoryConfig $config): GitHubRepository

$api = $this->createRepositoryApi($org, $repo);

return new GitHubRepository($api, $org, $repo, $this->logger, $this->registry);
return new GitHubRepository($api, $org, $repo, $this->logger, $this->registry, $config->tagPrefix);
}

/**
Expand Down
12 changes: 9 additions & 3 deletions src/Module/Repository/Internal/GitHub/GitHubRelease.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,31 @@ final class GitHubRelease extends Release implements Destroyable
{
/**
* @param non-empty-string $name
* @param non-empty-string $tag
*/
private function __construct(
GitHubRepository $repository,
string $name,
string $tag,
Version $version,
) {
parent::__construct($repository, $name, $version);
parent::__construct($repository, $name, $tag, $version);
}

/**
* @param string $tagPrefix Prefix the tag starts with; it is not part of the version.
* @throws \InvalidArgumentException When the release tag is not a version.
*/
public static function fromRecord(
RepositoryApi $api,
GitHubRepository $repository,
ReleaseRecord $record,
string $tagPrefix = '',
): self {
$version = Version::fromVersionString($record->tag);
$result = new self($repository, $record->name, $version);
$version = \substr($record->tag, \strlen($tagPrefix));
$version === '' and throw new \InvalidArgumentException("Release tag `{$record->tag}` has no version.");
$version = Version::fromVersionString($version);
$result = new self($repository, $record->name, $record->tag, $version);

$result->assets = AssetsCollection::create(static function () use ($api, $result, $record): \Generator {
foreach ($record->assets as $asset) {
Expand Down
8 changes: 7 additions & 1 deletion src/Module/Repository/Internal/GitHub/GitHubRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public function __construct(
string $repo,
private readonly Logger $logger,
private readonly VersionRegistry $registry,
private readonly string $tagPrefix = '',
) {
$this->name = $org . '/' . $repo;
}
Expand Down Expand Up @@ -83,8 +84,13 @@ public function getReleases(): ReleasesCollection

$toYield = [];
foreach ($pages->current() ?? [] as $record) {
// Releases of other components sharing the repository
if (!\str_starts_with($record->tag, $this->tagPrefix)) {
continue;
}

try {
$toYield[] = GitHubRelease::fromRecord($this->api, $this, $record);
$toYield[] = GitHubRelease::fromRecord($this->api, $this, $record, $this->tagPrefix);
} catch (\Throwable $e) {
$this->logger->exception($e, important: false);
// Skip invalid releases
Expand Down
6 changes: 3 additions & 3 deletions src/Module/Repository/Internal/GitLab/Api/RepositoryApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ public function __construct(

/**
* @param non-empty-string $repositoryPath
* @param non-empty-string $releaseName
* @param non-empty-string $tag Tag of the release; GitLab addresses release downloads by it, not by the release name.
* @param non-empty-string $fileName
* @throws RepositoryException
*/
public function downloadArtifact(string $repositoryPath, string $releaseName, string $fileName): ResponseInterface
public function downloadArtifact(string $repositoryPath, string $tag, string $fileName): ResponseInterface
{
$url = \sprintf(self::URL_RELEASE_ASSET, \urlencode($repositoryPath), $releaseName, $fileName);
$url = \sprintf(self::URL_RELEASE_ASSET, \urlencode($repositoryPath), \rawurlencode($tag), $fileName);
return $this->client->downloadArtifact($url);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Module/Repository/Internal/GitLab/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function create(RepositoryConfig $config): GitLabRepository
$uri = \is_string($path) && $path !== '' ? $path : $config->uri;
$api = $this->createRepositoryApi($uri);

return new GitLabRepository($api, $uri, $this->logger, $this->registry);
return new GitLabRepository($api, $uri, $this->logger, $this->registry, $config->tagPrefix);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Module/Repository/Internal/GitLab/GitLabAsset.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static function fromRecord(
*/
public function download(?\Closure $progress = null): \Generator
{
$response = $this->api->downloadArtifact($this->release->getRepository()->getName(), $this->release->getName(), $this->getName());
$response = $this->api->downloadArtifact($this->release->getRepository()->getName(), $this->release->getTag(), $this->getName());

yield from StreamReader::chunks($response->getBody(), $progress);
}
Expand Down
12 changes: 9 additions & 3 deletions src/Module/Repository/Internal/GitLab/GitLabRelease.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,31 @@ final class GitLabRelease extends Release implements Destroyable
{
/**
* @param non-empty-string $name
* @param non-empty-string $tag
*/
private function __construct(
GitLabRepository $repository,
string $name,
string $tag,
Version $version,
) {
parent::__construct($repository, $name, $version);
parent::__construct($repository, $name, $tag, $version);
}

/**
* @param string $tagPrefix Prefix the tag starts with; it is not part of the version.
* @throws \InvalidArgumentException When the release tag is not a version.
*/
public static function fromRecord(
RepositoryApi $api,
GitLabRepository $repository,
ReleaseRecord $record,
string $tagPrefix = '',
): self {
$version = Version::fromVersionString($record->tag);
$result = new self($repository, $record->name, $version);
$version = \substr($record->tag, \strlen($tagPrefix));
$version === '' and throw new \InvalidArgumentException("Release tag `{$record->tag}` has no version.");
$version = Version::fromVersionString($version);
$result = new self($repository, $record->name, $record->tag, $version);
Comment thread
roxblnfk marked this conversation as resolved.

$result->assets = AssetsCollection::create(static function () use ($api, $result, $record): \Generator {
foreach ($record->assets as $asset) {
Expand Down
8 changes: 7 additions & 1 deletion src/Module/Repository/Internal/GitLab/GitLabRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function __construct(
string $projectPath,
private readonly Logger $logger,
private readonly VersionRegistry $registry,
private readonly string $tagPrefix = '',
) {
$this->name = $projectPath;
}
Expand Down Expand Up @@ -81,8 +82,13 @@ public function getReleases(): ReleasesCollection

$toYield = [];
foreach ($pages->current() ?? [] as $record) {
// Releases of other components sharing the repository
if (!\str_starts_with($record->tag, $this->tagPrefix)) {
continue;
}

try {
$toYield[] = GitLabRelease::fromRecord($this->api, $this, $record);
$toYield[] = GitLabRelease::fromRecord($this->api, $this, $record, $this->tagPrefix);
} catch (\Throwable) {
// Skip invalid releases
continue;
Expand Down
7 changes: 7 additions & 0 deletions src/Module/Repository/Internal/Release.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ abstract class Release implements ReleaseInterface

/**
* @param non-empty-string $name Release name.
* @param non-empty-string $tag Tag the release was made from.
*/
public function __construct(
protected Repository $repository,
protected string $name,
protected string $tag,
protected Version $version,
iterable $assets = [],
) {
Expand All @@ -40,6 +42,11 @@ public function getName(): string
return $this->name;
}

public function getTag(): string
{
return $this->tag;
}

public function getVersion(): Version
{
return $this->version;
Expand Down
Loading
Loading