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
70 changes: 70 additions & 0 deletions app/Domains/Package/Contracts/Data/PackageVersionData.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public function __construct(
public ?CarbonInterface $releasedAt,
public ?string $sourceUrl,
public ?string $sourceReference,
public ?string $sourceTag,
public ?string $commitUrl,
public ?string $tagUrl,
public ?int $distSize,
public int $vulnerabilityCount = 0,
public ?AdvisorySeverity $highestSeverity = null,
Expand Down Expand Up @@ -56,14 +58,31 @@ public static function fromModel(
$highestSeverity = $highestWeight ? AdvisorySeverity::fromWeight($highestWeight) : null;
}

$tagUrl = null;

if ($version->source_tag && $version->source_url) {
$versionProvider ??= $version->package->repository?->provider;
$versionRepoIdentifier ??= $version->package->repository?->repo_identifier;

$tagUrl = static::generateTagUrl(
sourceUrl: $version->source_url,
sourceTag: $version->source_tag,
version: $version->version,
provider: $versionProvider,
repoIdentifier: $versionRepoIdentifier,
);
}

return new self(
uuid: $version->uuid,
version: $version->version,
normalizedVersion: $version->normalized_version,
releasedAt: $version->released_at,
sourceUrl: $version->source_url,
sourceReference: $version->source_reference,
sourceTag: $version->source_tag,
commitUrl: $commitUrl,
tagUrl: $tagUrl,
distSize: $version->dist_size,
vulnerabilityCount: $vulnerabilityCount,
highestSeverity: $highestSeverity,
Expand Down Expand Up @@ -127,6 +146,57 @@ protected static function generateCommitUrlFromSourceUrl(
return null;
}

protected static function generateTagUrl(
?string $sourceUrl,
string $sourceTag,
string $version,
?GitProvider $provider,
?string $repoIdentifier
): ?string {
// Dev branches should not get tag URLs
if (str_starts_with($version, 'dev-') || str_ends_with($version, '-dev')) {
return null;
}

if ($provider && $repoIdentifier) {
return match ($provider) {
GitProvider::GitHub => "https://github.com/{$repoIdentifier}/releases/tag/{$sourceTag}",
GitProvider::GitLab => "https://gitlab.com/{$repoIdentifier}/-/tags/{$sourceTag}",
GitProvider::Bitbucket => "https://bitbucket.org/{$repoIdentifier}/src/{$sourceTag}",
GitProvider::Git => static::generateTagUrlFromSourceUrl($sourceUrl, $sourceTag),
};
}

return static::generateTagUrlFromSourceUrl($sourceUrl, $sourceTag);
}

protected static function generateTagUrlFromSourceUrl(
?string $sourceUrl,
string $sourceTag
): ?string {
if (! $sourceUrl) {
return null;
}

$cleanUrl = preg_replace('/^git@/', '', $sourceUrl) ?? '';
$cleanUrl = preg_replace('/\.git$/', '', $cleanUrl) ?? '';
$cleanUrl = str_replace(':', '/', $cleanUrl);

if (str_starts_with($cleanUrl, 'github.com/')) {
return "https://{$cleanUrl}/releases/tag/{$sourceTag}";
}

if (str_starts_with($cleanUrl, 'gitlab.com/')) {
return "https://{$cleanUrl}/-/tags/{$sourceTag}";
}

if (str_starts_with($cleanUrl, 'bitbucket.org/')) {
return "https://{$cleanUrl}/src/{$sourceTag}";
}

return null;
}

public function isStable(): bool
{
return ! str_contains($this->version, 'dev') && preg_match('/^\d+\.\d+/', $this->version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ public function __construct(
public ?CarbonInterface $releasedAt,
public ?string $sourceUrl,
public ?string $sourceReference,
public ?string $sourceTag,
public ?string $commitUrl,
public ?string $tagUrl,
public ?string $description,
public ?string $type,
public ?string $license,
Expand Down Expand Up @@ -70,7 +72,9 @@ public static function fromModel(
releasedAt: $base->releasedAt,
sourceUrl: $base->sourceUrl,
sourceReference: $base->sourceReference,
sourceTag: $base->sourceTag,
commitUrl: $base->commitUrl,
tagUrl: $base->tagUrl,
description: $composerJson['description'] ?? null,
type: $composerJson['type'] ?? null,
license: $license,
Expand Down
2 changes: 2 additions & 0 deletions app/Domains/Repository/Actions/SyncRefAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public function handle(
'composer_json' => $metadata->composerJson,
'source_url' => $sourceUrl,
'source_reference' => $ref->commit,
'source_tag' => $ref->name,
]);

return ['status' => 'updated', 'version' => $version, 'package' => $package];
Expand All @@ -88,6 +89,7 @@ public function handle(
'composer_json' => $metadata->composerJson,
'source_url' => $sourceUrl,
'source_reference' => $ref->commit,
'source_tag' => $ref->name,
'released_at' => now(),
]);

Expand Down
1 change: 1 addition & 0 deletions app/Models/PackageVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* @property array<array-key, mixed> $composer_json
* @property string|null $source_url
* @property string|null $source_reference
* @property string|null $source_tag
* @property string|null $dist_url
* @property string|null $dist_shasum
* @property string|null $dist_path
Expand Down
2 changes: 2 additions & 0 deletions database/factories/PackageVersionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function definition(): array
'composer_json' => $this->generateComposerJson($version),
'source_url' => fake()->url(),
'source_reference' => fake()->sha1(),
'source_tag' => "v{$version}",
'dist_url' => fake()->url().'/archive/'.$version.'.zip',
'released_at' => fake()->dateTimeBetween('-2 years', 'now'),
];
Expand Down Expand Up @@ -94,6 +95,7 @@ public function devBranch(string $branch = 'main'): static
return [
'version' => $version,
'normalized_version' => '9999999-dev',
'source_tag' => null,
'composer_json' => array_merge($attributes['composer_json'] ?? [], [
'version' => $version,
]),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('package_versions', function (Blueprint $table) {
$table->string('source_tag')->nullable()->after('source_reference');
});
}

public function down(): void
{
Schema::table('package_versions', function (Blueprint $table) {
$table->dropColumn('source_tag');
});
}
};
36 changes: 36 additions & 0 deletions resources/js/pages/organizations/packages/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
Package as PackageIcon,
Search,
ShieldAlert,
Tag,
Terminal,
Trash2,
Users,
Expand Down Expand Up @@ -564,6 +565,22 @@ export default function PackageShow({
)}
</span>
)}
{version.tagUrl && (
<a
href={
version.tagUrl
}
target="_blank"
rel="noopener noreferrer"
onClick={(e) =>
e.stopPropagation()
}
className="flex items-center gap-1 hover:text-foreground hover:underline"
>
<Tag className="h-3.5 w-3.5" />
{version.sourceTag}
</a>
)}
</div>
</div>
<CopyInstallButton
Expand Down Expand Up @@ -733,6 +750,25 @@ export default function PackageShow({
)}
</div>
)}
{activeVersion.tagUrl && (
<div>
<div className="mb-1.5 flex items-center gap-1.5 text-sm font-medium text-muted-foreground">
<Tag className="h-4 w-4" />
Tag
</div>
<a
href={
activeVersion.tagUrl
}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1.5 font-medium text-muted-foreground transition-colors hover:text-foreground hover:underline"
>
{activeVersion.sourceTag}
<ExternalLink className="h-3.5 w-3.5" />
</a>
</div>
)}
</div>

{/* Install command */}
Expand Down
4 changes: 4 additions & 0 deletions resources/types/generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ normalizedVersion: string;
releasedAt: string | null;
sourceUrl: string | null;
sourceReference: string | null;
sourceTag: string | null;
commitUrl: string | null;
tagUrl: string | null;
distSize: number | null;
vulnerabilityCount: number;
highestSeverity: App.Domains.Security.Contracts.Enums.AdvisorySeverity | null;
Expand All @@ -174,7 +176,9 @@ normalizedVersion: string;
releasedAt: string | null;
sourceUrl: string | null;
sourceReference: string | null;
sourceTag: string | null;
commitUrl: string | null;
tagUrl: string | null;
description: string | null;
type: string | null;
license: string | null;
Expand Down