Skip to content
This repository has been archived by the owner on Jul 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #22 from chainguard-dev/production-images
Browse files Browse the repository at this point in the history
Production Images Update
  • Loading branch information
erikaheidi committed Mar 1, 2024
2 parents 464ce1e + 248f1e8 commit 4dc041f
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 144 deletions.
88 changes: 88 additions & 0 deletions app/Command/Build/DatafeedsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace App\Command\Build;

use App\ImageCollection;
use Autodocs\DataFeed\JsonDataFeed;
use Autodocs\Exception\NotFoundException;
use autodocs\Service\AutodocsService;
use Minicli\Command\CommandController;
use Exception;
use TypeError;

class DatafeedsController extends CommandController
{
/**
* @throws NotFoundException
*/
public function handle(): void
{
/** @var AutodocsService $autodocs */
$autodocs = $this->getApp()->autodocs;

try {
$imagesDevList = $autodocs->getDataFeed('images-tags-dev.json');
$imagesProdList = $autodocs->getDataFeed('images-tags-prod.json');
} catch (Exception $exception) {
$this->error("Error: ".$exception->getMessage());
return;
} catch (TypeError $error) {
$this->error("Error: ".$error->getMessage());
return;
}

$cacheDev = $this->getApp()->autodocs->config['cache_dir'].'/images-dev';
$cacheProd = $this->getApp()->autodocs->config['cache_dir'].'/images-prod';

$images = new ImageCollection();
//all dev images are in the prod list, the opposite is not true. use prod images as source of truth
foreach ($imagesProdList->json as $imageInfo) {
$image = $images->get($imageInfo['repo']['name'], true);
$image->tagsProd = $imageInfo['tags'];
if (array_key_exists('readme', $imageInfo['repo'])) {
$image->readmeProd = $imageInfo['repo']['readme'];
}
$image->variants = $this->getImageConfigs($image->getName(), $cacheProd);
$images->add($image);
$autodocs->storage->saveFile($autodocs->config['cache_dir'].'/datafeeds/'.$image->name.".json", $image->getJson());
}
//get complimentary information about public tags, readme
foreach ($imagesDevList->json as $imageInfo) {
$image = $images->get($imageInfo['repo']['name'], true);
$image->tagsDev = $imageInfo['tags'];
if (array_key_exists('readme', $imageInfo['repo'])) {
$image->readmeDev = $imageInfo['repo']['readme'];
}
$images->add($image);
$autodocs->storage->saveFile($autodocs->config['cache_dir'].'/datafeeds/'.$image->name.".json", $image->getJson());
}

$this->success("Finished building image Datafeeds based on cached data.");
}

/**
* @throws NotFoundException
*/
public function getImageConfigs(string $image, string $cachePath): array
{
$variantsList = [];

foreach (glob($cachePath.'/*.json') as $imageConfig) {
if (str_starts_with(basename($imageConfig), $image.'.latest')) {

list($imageName, $variantName, $extension) = explode('.', basename($imageConfig));
try {
$dataFeed = new JsonDataFeed();
$dataFeed->loadFile($imageConfig);
$variantsList[$variantName] = $dataFeed->json;
} catch (TypeError $e) {
//json might have issues. skip
}
}
}

return $variantsList;
}
}
15 changes: 12 additions & 3 deletions app/Command/Build/ImagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@

use App\ImageChangelog;
use App\Page\ChangelogPage;
use Autodocs\DataFeed\JsonDataFeed;
use Autodocs\Exception\NotFoundException;
use autodocs\Service\AutodocsService;
use Minicli\Command\CommandController;
use Exception;
use TypeError;

class ImagesController extends CommandController
{
/**
* @throws NotFoundException
*/
public function handle(): void
{
/** @var AutodocsService $autodocs */
Expand All @@ -21,6 +26,7 @@ public function handle(): void
$changelog = new ImageChangelog($autodocs->config['output']);
$changelog->capture();

/*
try {
$imagesList = $autodocs->getDataFeed($autodocs->config['cache_images_file']);
} catch (Exception $exception) {
Expand All @@ -29,13 +35,16 @@ public function handle(): void
} catch (TypeError $error) {
$this->error("Error: ".$error->getMessage());
return;
}
}*/


if ($this->hasParam('image')) {
$this->buildDocsForImage($this->getParam('image'));
} else {
foreach ($imagesList->json as $image) {
$imageName = $image['repo']['name'];
foreach (glob($autodocs->config['cache_dir'].'/datafeeds/*.json') as $imageCache) {
$dataFeed = new JsonDataFeed();
$dataFeed->loadFile($imageCache);
$imageName = $dataFeed->json['name'];
$this->buildDocsForImage($imageName);
}
}
Expand Down
88 changes: 88 additions & 0 deletions app/Image.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace App;

use Autodocs\DataFeed\JsonDataFeed;
use Autodocs\Exception\NotFoundException;
use Autodocs\Mark;

class Image
{
public string $name;

public string $readmeDev = "";
public string $readmeProd = "";
public array $tagsDev = [];
public array $tagsProd = [];
public array $variants = [];

public function __construct(string $name)
{
$this->name = $name;
}

public function getName(): string
{
return $this->name;
}

public function getJson(): string
{
return json_encode([
'name' => $this->name,
'tagsDev' => $this->tagsDev,
'tagsProd' => $this->tagsProd,
'readmeDev' => $this->readmeDev,
'readmeProd' => $this->readmeProd,
'variants' => $this->variants,
]);
}

public function getReadme(string $fallback): string
{
if ("" === $this->readmeDev || empty($this->readmeDev)) {
if ("" === $this->readmeProd || empty($this->readmeProd)) {
return $fallback;
}
return $this->readmeProd;
}
return $this->readmeDev;
}

public function getRegistryTagsTable(): string
{
$tagsDev = $tagsProd = [];
foreach ($this->tagsDev as $tag) {
$tagsDev[] = $tag['name'];
}
foreach ($this->tagsProd as $tag) {
$tagsProd[] = $tag['name'];
}
$rows = [
['`cgr.dev/chainguard`', count($tagsDev) ? implode(', ', $tagsDev) : "No public tags are available for this image."],
['`cgr.dev/chainguard-private`', count($tagsProd) ? implode(', ', $tagsProd) : "No production tags are available for this image."]
];

return Mark::table($rows, ['Registry', 'Tags']);
}

/**
* @throws NotFoundException
*/
public static function loadFromDatafeed(string $datafeed): Image
{
$imageDatafeed = new JsonDataFeed();
$imageDatafeed->loadFile($datafeed);
$image = new Image($imageDatafeed->json['name']);

$image->tagsDev = $imageDatafeed->json['tagsDev'];
$image->tagsProd = $imageDatafeed->json['tagsProd'];
$image->readmeDev = $imageDatafeed->json['readmeDev'];
$image->readmeProd = $imageDatafeed->json['readmeProd'];
$image->variants = $imageDatafeed->json['variants'];

return $image;
}
}
43 changes: 43 additions & 0 deletions app/ImageCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace App;

class ImageCollection
{
protected array $images = [];

public function add(Image $image): void
{
$this->images[] = $image;
}

public function addImages(array $images): void
{
foreach ($images as $image) {
$this->add($image);
}
}

public function getImages(): array
{
return $this->images;
}

public function get(string $imageName, $createNew = false): ?Image
{
/** @var Image $image */
foreach ($this->images as $image) {
if ($image->getName() === $imageName) {
return $image;
}
}

if ($createNew) {
return new Image($imageName);
}

return null;
}
}
39 changes: 8 additions & 31 deletions app/Page/OverviewPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace App\Page;

use App\Image;
use Autodocs\Exception\NotFoundException;
use Autodocs\Page\ReferencePage;
use Minicli\FileNotFoundException;

Expand All @@ -16,35 +18,6 @@ public function loadData(array $parameters = []): void
$this->image = $parameters['image'];
}

/**
* @throws FileNotFoundException
*/
public function findReadme(string $image): string
{
$imagesList = $this->autodocs->getDataFeed($this->autodocs->config['cache_images_file']);
foreach ($imagesList->json as $imageInfo) {
if ($imageInfo['repo']['name'] === $image) {
if (array_key_exists('readme', $imageInfo['repo'])) {
return $imageInfo['repo']['readme'];
}

//readme not defined, try to find from annotation
$imageMeta = $this->autodocs->getDataFeed("{$image}.latest.json");
$image_source = $imageMeta->json["predicate"]["annotations"]["org.opencontainers.image.source"];
$image_source = explode("/", $image_source);
$referenceImage = end($image_source);
if ($referenceImage !== $image) {
$this->findReadme($referenceImage);
}
}
}

//no readme found, return fallback template
return $this->autodocs->stencil->applyTemplate('image_overview_fallback', [
'image' => $this->image
]);
}

public function getName(): string
{
return 'overview';
Expand All @@ -56,11 +29,15 @@ public function getSavePath(): string
}

/**
* @throws FileNotFoundException
* @throws FileNotFoundException|NotFoundException
*/
public function getContent(): string
{
$readme = $this->findReadme($this->image);
$image = Image::loadFromDatafeed($this->autodocs->config['cache_dir'].'/datafeeds/'.$this->image.".json");
$fallback = $this->autodocs->stencil->applyTemplate('image_overview_fallback', [
'image' => $this->image
]);
$readme = $image->getReadme($fallback);

$readme = str_ireplace("# {$readme}", "", $readme);
$readme = preg_replace('/<!--monopod:start-->(.*)<!--monopod:end-->/Uis', '', $readme);
Expand Down
8 changes: 7 additions & 1 deletion app/Page/ProvenancePage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace App\Page;

use App\Image;
use Autodocs\Exception\NotFoundException;
use Autodocs\Page\ReferencePage;
use Minicli\FileNotFoundException;

Expand All @@ -27,12 +29,16 @@ public function getSavePath(): string

/**
* @throws FileNotFoundException
* @throws NotFoundException
*/
public function getContent(): string
{
$image = Image::loadFromDatafeed($this->autodocs->config['cache_dir'].'/datafeeds/'.$this->image.".json");

return $this->autodocs->stencil->applyTemplate('image_provenance_page', [
'title' => $this->image,
'description' => "Provenance information for {$this->image} Chainguard Image"
'description' => "Provenance information for {$this->image} Chainguard Image",
'registryTags' => $image->getRegistryTagsTable()
]);
}
}
Loading

0 comments on commit 4dc041f

Please sign in to comment.