From 03157d841e4b1fe13dd430342ef3225008aba1e1 Mon Sep 17 00:00:00 2001
From: Joxit
Date: Thu, 25 May 2023 07:01:50 +0200
Subject: [PATCH 1/4] test(branching): start new configurable branching
repository system
---
src/scripts/repositories.js | 27 +++++++++++++++++++++++++++
test/repositories.test.js | 31 +++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
create mode 100644 src/scripts/repositories.js
create mode 100644 test/repositories.test.js
diff --git a/src/scripts/repositories.js b/src/scripts/repositories.js
new file mode 100644
index 0000000..caf9d1d
--- /dev/null
+++ b/src/scripts/repositories.js
@@ -0,0 +1,27 @@
+const getRepositoryName = (split, max) => {
+ let repositoryName = '';
+ for (let i = 0; i < max; i++) {
+ repositoryName += `${split[i]}/`;
+ }
+ return repositoryName;
+};
+
+export const getBranching =
+ (min = 1, max = 1) =>
+ (repositories) =>
+ repositories.sort().reduce(function (acc, image) {
+ const split = image.split('/');
+ if (split.length > min && min > 0) {
+ const repoName = getRepositoryName(split, max);
+ if (acc.length === 0 || acc[acc.length - 1].repo != repoName) {
+ acc.push({
+ repo: repoName,
+ images: [],
+ });
+ }
+ acc[acc.length - 1].images.push(image);
+ return acc;
+ }
+ acc.push(image);
+ return acc;
+ }, []);
diff --git a/test/repositories.test.js b/test/repositories.test.js
new file mode 100644
index 0000000..d8bc125
--- /dev/null
+++ b/test/repositories.test.js
@@ -0,0 +1,31 @@
+import { getBranching } from '../src/scripts/repositories.js';
+import assert from 'assert';
+
+describe('repositories', () => {
+ describe('getBranching', () => {
+ it('should not branch for no levels', () => {
+ const branching = getBranching(0, 0);
+ assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']);
+ assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [
+ 'alpine',
+ 'joxit/docker-registry-ui',
+ 'nginx',
+ ]);
+ });
+
+ it('should branch for one level', () => {
+ const branching = getBranching(1, 1);
+ assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']);
+ assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [
+ 'alpine',
+ { images: ['joxit/docker-registry-ui'], repo: 'joxit/' },
+ 'nginx',
+ ]);
+ assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'nginx']), [
+ 'alpine',
+ { images: ['joxit/docker-registry-ui', 'joxit/kokai'], repo: 'joxit/' },
+ 'nginx',
+ ]);
+ });
+ });
+});
From 398fa65fa17189407ffa4f2e879f3de3f3e52e8a Mon Sep 17 00:00:00 2001
From: Joxit
Date: Mon, 29 May 2023 15:38:38 +0200
Subject: [PATCH 2/4] test(branching): add new test for custom branching
---
src/scripts/repositories.js | 48 +++++++++++++++----
test/repositories.test.js | 96 +++++++++++++++++++++++++++++++++++--
2 files changed, 133 insertions(+), 11 deletions(-)
diff --git a/src/scripts/repositories.js b/src/scripts/repositories.js
index caf9d1d..1eac2ca 100644
--- a/src/scripts/repositories.js
+++ b/src/scripts/repositories.js
@@ -1,27 +1,59 @@
+import { DockerRegistryUIError } from './error.js';
+
const getRepositoryName = (split, max) => {
let repositoryName = '';
- for (let i = 0; i < max; i++) {
+ for (let i = 0; i < Math.min(max, split.length - 1); i++) {
repositoryName += `${split[i]}/`;
}
return repositoryName;
};
-export const getBranching =
- (min = 1, max = 1) =>
- (repositories) =>
+const getLatestRepository = (repo, repoName) => {
+ if (!repo.images) {
+ return;
+ }
+ if (repo.repo === repoName) {
+ return repo;
+ }
+ for (let i = 0; i < repo.images.length; i++) {
+ const res = getLatestRepository(repo.images[i], repoName);
+ if (res) {
+ return res;
+ }
+ }
+
+ if (repoName.startsWith(repo.repo)) {
+ const newRepo = { repo: repoName, images: [] };
+ repo.images.push(newRepo);
+ return newRepo;
+ }
+};
+
+export const getBranching = (min = 1, max = 1) => {
+ if (min > max) {
+ throw new DockerRegistryUIError(`min must be inferior to max (min: ${min} <= max: ${max})`);
+ } else if (max < 0 || min < 0) {
+ throw new DockerRegistryUIError(
+ `min and max must be greater than equals to 0 (min: ${min} >= 0 and max: ${max} >= 0)`
+ );
+ }
+ return (repositories) =>
repositories.sort().reduce(function (acc, image) {
const split = image.split('/');
if (split.length > min && min > 0) {
const repoName = getRepositoryName(split, max);
- if (acc.length === 0 || acc[acc.length - 1].repo != repoName) {
- acc.push({
+ let repo = acc.length > 0 && getLatestRepository(acc[acc.length - 1], repoName);
+ if (!repo) {
+ repo = {
repo: repoName,
images: [],
- });
+ };
+ acc.push(repo);
}
- acc[acc.length - 1].images.push(image);
+ repo.images.push(image);
return acc;
}
acc.push(image);
return acc;
}, []);
+};
diff --git a/test/repositories.test.js b/test/repositories.test.js
index d8bc125..4e96e5c 100644
--- a/test/repositories.test.js
+++ b/test/repositories.test.js
@@ -1,4 +1,5 @@
import { getBranching } from '../src/scripts/repositories.js';
+import { DockerRegistryUIError } from '../src/scripts/error.js';
import assert from 'assert';
describe('repositories', () => {
@@ -6,9 +7,10 @@ describe('repositories', () => {
it('should not branch for no levels', () => {
const branching = getBranching(0, 0);
assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']);
- assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [
+ assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/docker-registry-ui/amd64', 'nginx']), [
'alpine',
'joxit/docker-registry-ui',
+ 'joxit/docker-registry-ui/amd64',
'nginx',
]);
});
@@ -21,11 +23,99 @@ describe('repositories', () => {
{ images: ['joxit/docker-registry-ui'], repo: 'joxit/' },
'nginx',
]);
- assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'nginx']), [
+ assert.deepEqual(
+ branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'joxit/docker-registry-ui/amd64', 'nginx']),
+ [
+ 'alpine',
+ { images: ['joxit/docker-registry-ui', 'joxit/docker-registry-ui/amd64', 'joxit/kokai'], repo: 'joxit/' },
+ 'nginx',
+ ]
+ );
+ });
+
+ it('should branch for two level', () => {
+ const branching = getBranching(2, 2);
+ assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']);
+ assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [
+ 'alpine',
+ 'joxit/docker-registry-ui',
+ 'nginx',
+ ]);
+ assert.deepEqual(
+ branching([
+ 'alpine',
+ 'joxit/docker-registry-ui',
+ 'joxit/kokai',
+ 'joxit/docker-registry-ui/amd64',
+ 'joxit/docker-registry-ui/amd64/latest',
+ 'joxit/docker-registry-ui/armv7',
+ 'joxit/docker-registry-ui/armv7/latest',
+ 'nginx',
+ ]),
+ [
+ 'alpine',
+ 'joxit/docker-registry-ui',
+ {
+ images: [
+ 'joxit/docker-registry-ui/amd64',
+ 'joxit/docker-registry-ui/amd64/latest',
+ 'joxit/docker-registry-ui/armv7',
+ 'joxit/docker-registry-ui/armv7/latest',
+ ],
+ repo: 'joxit/docker-registry-ui/',
+ },
+ 'joxit/kokai',
+ 'nginx',
+ ]
+ );
+ });
+
+ it('should branch from one to two level', () => {
+ const branching = getBranching(1, 2);
+ assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']);
+ assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [
'alpine',
- { images: ['joxit/docker-registry-ui', 'joxit/kokai'], repo: 'joxit/' },
+ { images: ['joxit/docker-registry-ui'], repo: 'joxit/' },
'nginx',
]);
+ assert.deepEqual(
+ branching([
+ 'alpine',
+ 'joxit/docker-registry-ui',
+ 'joxit/kokai',
+ 'joxit/docker-registry-ui/amd64',
+ 'joxit/docker-registry-ui/amd64/latest',
+ 'joxit/docker-registry-ui/armv7',
+ 'joxit/docker-registry-ui/armv7/latest',
+ 'nginx',
+ ]),
+ [
+ 'alpine',
+ {
+ images: [
+ 'joxit/docker-registry-ui',
+ {
+ images: [
+ 'joxit/docker-registry-ui/amd64',
+ 'joxit/docker-registry-ui/amd64/latest',
+ 'joxit/docker-registry-ui/armv7',
+ 'joxit/docker-registry-ui/armv7/latest',
+ ],
+ repo: 'joxit/docker-registry-ui/',
+ },
+ 'joxit/kokai',
+ ],
+ repo: 'joxit/',
+ },
+ 'nginx',
+ ]
+ );
});
});
+
+ it('should branch from one to two level', () => {
+ assert.throws(() => getBranching(2, 1), DockerRegistryUIError, `Did not throw on min > max`);
+ assert.throws(() => getBranching(-2, 1), DockerRegistryUIError, `Did not throw on min < 0`);
+ assert.throws(() => getBranching(2, -1), DockerRegistryUIError, `Did not throw on max < 0`);
+ });
});
From 1031034bc4fc44c66ce4a4c87a87d29fb19bbf20 Mon Sep 17 00:00:00 2001
From: Joxit
Date: Tue, 30 May 2023 07:49:18 +0200
Subject: [PATCH 3/4] feat(branching): add configuration for catalog
arborescence
---
bin/90-docker-registry-ui.sh | 2 ++
src/components/catalog/catalog-element.riot | 7 ++++
src/components/catalog/catalog.riot | 39 ++++++++++++---------
src/components/docker-registry-ui.riot | 32 +++++++++--------
src/components/error-page.riot | 4 +++
src/components/tag-history/tag-history.riot | 1 -
src/index.html | 4 +++
src/scripts/error.js | 3 +-
src/scripts/repositories.js | 17 +++++++--
src/style.scss | 13 +++----
test/repositories.test.js | 1 +
11 files changed, 80 insertions(+), 43 deletions(-)
diff --git a/bin/90-docker-registry-ui.sh b/bin/90-docker-registry-ui.sh
index c9c732f..94fd0ab 100755
--- a/bin/90-docker-registry-ui.sh
+++ b/bin/90-docker-registry-ui.sh
@@ -13,6 +13,8 @@ sed -i "s~\${HISTORY_CUSTOM_LABELS}~${HISTORY_CUSTOM_LABELS}~" index.html
sed -i "s~\${USE_CONTROL_CACHE_HEADER}~${USE_CONTROL_CACHE_HEADER}~" index.html
sed -i "s~\${TAGLIST_ORDER}~${TAGLIST_ORDER}~" index.html
sed -i "s~\${CATALOG_DEFAULT_EXPANDED}~${CATALOG_DEFAULT_EXPANDED}~" index.html
+sed -i "s~\${CATALOG_MIN_BRANCHES}~${CATALOG_MIN_BRANCHES}~" index.html
+sed -i "s~\${CATALOG_MAX_BRANCHES}~${CATALOG_MAX_BRANCHES}~" index.html
grep -o 'THEME[A-Z_]*' index.html | while read e; do
sed -i "s~\${$e}~$(printenv $e)~" index.html
diff --git a/src/components/catalog/catalog-element.riot b/src/components/catalog/catalog-element.riot
index 788ae9b..b235056 100644
--- a/src/components/catalog/catalog-element.riot
+++ b/src/components/catalog/catalog-element.riot
@@ -52,6 +52,7 @@ along with this program. If not, see .
show-catalog-nb-tags="{ props.showCatalogNbTags }"
class="animated {!state.expanded && !props.filterResults ? 'hide' : ''} {state.expanding ? 'expanding' : ''}"
each="{item in state.images}"
+ z-index="{ props.zIndex - 1 }"
item="{ item }"
>
@@ -76,6 +77,12 @@ along with this program. If not, see .
this.getNbTags(props, state);
}
},
+ onMounted(props, state) {
+ const materialCard = this.$('material-card');
+ if (materialCard) {
+ materialCard.style['z-index'] = props.zIndex;
+ }
+ },
onBeforeUpdate(props, state) {
if (props.filterResults && state.images) {
state.nImages = state.images.filter((image) => matchSearch(props.filterResults, image)).length;
diff --git a/src/components/catalog/catalog.riot b/src/components/catalog/catalog.riot
index 91aea31..3365a2f 100644
--- a/src/components/catalog/catalog.riot
+++ b/src/components/catalog/catalog.riot
@@ -35,10 +35,12 @@ along with this program. If not, see .
on-authentication="{ props.onAuthentication }"
show-catalog-nb-tags="{ props.showCatalogNbTags }"
catalog-default-expanded="{ props.catalogDefaultExpanded || state.nRepositories === 1 }"
+ z-index="{ props.catalogMaxBranches - props.catalogMinBranches + 2 }"
>
+
diff --git a/src/components/docker-registry-ui.riot b/src/components/docker-registry-ui.riot
index 5f39d37..1ea7032 100644
--- a/src/components/docker-registry-ui.riot
+++ b/src/components/docker-registry-ui.riot
@@ -31,6 +31,21 @@ along with this program. If not, see .
+
+
.
on-authentication="{ onAuthentication }"
show-catalog-nb-tags="{ truthy(props.showCatalogNbTags) }"
catalog-default-expanded="{ truthy(props.catalogDefaultExpanded) }"
+ catalog-min-branches="{ props.catalogMinBranches }"
+ catalog-max-branches="{ props.catalogMaxBranches }"
>
@@ -82,21 +99,6 @@ along with this program. If not, see .
on-authenticated="{ state.onAuthenticated }"
opened="{ state.authenticationDialogOpened }"
>
-
-
+
+ Wrong configuration for the branching feature: { props.message }
+ Configuration environment variables are : CATALOG_MIN_BRANCH and CATALOG_MAX_BRANCH
+