8 Commits

Author SHA1 Message Date
ccb85e16fa new tier output
All checks were successful
Unit tests / Unit tests (lts/*) (push) Successful in -1m59s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m59s
NPM Audit Check / Check NPM audit (push) Successful in -2m1s
Distribution check / Generated files check (push) Successful in -1m57s
Unit tests / Unit tests (latest) (push) Successful in -1m59s
2025-11-12 14:52:04 -05:00
8170ed0565 Add logging
All checks were successful
Distribution check / Generated files check (push) Successful in -1m58s
NPM Audit Check / Check NPM audit (push) Successful in -2m9s
Unit tests / Unit tests (latest) (push) Successful in -1m59s
Unit tests / Unit tests (lts/*) (push) Successful in -1m59s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m58s
2025-11-12 12:25:30 -05:00
112afbe142 update dist
All checks were successful
Unit tests / Unit tests (latest) (push) Successful in -1m49s
Unit tests / Unit tests (lts/*) (push) Successful in -1m59s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m59s
Distribution check / Generated files check (push) Successful in -1m48s
NPM Audit Check / Check NPM audit (push) Successful in -2m9s
2025-11-12 11:55:13 -05:00
fc87114c36 use repo name
Some checks failed
NPM Audit Check / Check NPM audit (push) Successful in -2m9s
Unit tests / Unit tests (latest) (push) Successful in -1m59s
Unit tests / Unit tests (lts/*) (push) Successful in -2m0s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m59s
Distribution check / Generated files check (push) Failing after -1m57s
2025-11-11 01:10:56 -05:00
8f96ff74ec link package to repo
All checks were successful
Distribution check / Generated files check (push) Successful in -1m58s
NPM Audit Check / Check NPM audit (push) Successful in -2m10s
Unit tests / Unit tests (latest) (push) Successful in -2m0s
Unit tests / Unit tests (lts/*) (push) Successful in -2m0s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m59s
2025-11-11 01:04:50 -05:00
8574ca8ecb Export with dep repos
All checks were successful
Unit tests / Unit tests (latest) (push) Successful in -1m59s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -2m0s
Distribution check / Generated files check (push) Successful in -1m58s
NPM Audit Check / Check NPM audit (push) Successful in -2m10s
Unit tests / Unit tests (lts/*) (push) Successful in -2m0s
2025-11-09 23:57:42 -05:00
dd6940a77f Add license
All checks were successful
Distribution check / Generated files check (push) Successful in -1m58s
NPM Audit Check / Check NPM audit (push) Successful in -2m9s
Unit tests / Unit tests (latest) (push) Successful in -1m59s
Unit tests / Unit tests (lts/*) (push) Successful in -1m59s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m59s
2025-11-09 19:20:19 -05:00
8ce406f86a delete old package
All checks were successful
Distribution check / Generated files check (push) Successful in -1m56s
NPM Audit Check / Check NPM audit (push) Successful in -2m10s
Unit tests / Unit tests (lts/hydrogen) (push) Successful in -1m56s
Unit tests / Unit tests (latest) (push) Successful in -1m57s
Unit tests / Unit tests (lts/*) (push) Successful in -1m56s
2025-11-09 17:42:31 -05:00
9 changed files with 168 additions and 21 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Cory Sanin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -31,6 +31,10 @@ outputs:
description: whether a deletion is required or not
destination:
description: destination repo
deps:
description: which repos to enable while building (stable, testing, staging)
tier:
description: which tier of repos to enable (0 for system/core, etc.)
runs:
using: 'node16'

45
dist/index.js vendored
View File

@@ -41396,6 +41396,8 @@ async function parse(previous, current) {
build: false,
move: [],
delete: [],
deps: getDepRepo(actions.addRepo),
tier: getTier(actions.addRepo || actions.removeRepo),
actions,
};
// can't delete if there's nothing to delete/no previous success
@@ -41404,11 +41406,11 @@ async function parse(previous, current) {
result.delete.push(...parseRepoContents(repo, actions.removeRepo));
}
else if (isMove(actions)) {
const moving = result.move = parseRepoContents(curr.repos[actions.addRepo], actions.removeRepo);
prev && result.delete.push(...getDropped(parseRepoContents(prev.repos[actions.addRepo], actions.addRepo), moving));
result.move = parseRepoContents(curr.repos[actions.addRepo], actions.removeRepo);
prev && result.delete.push(...parseRepoContents(prev.repos[actions.addRepo], actions.addRepo));
}
else if ((result.build = isAdd(actions)) && prev) {
result.delete.push(...getDropped(parseRepoContents(prev.repos[actions.addRepo], actions.addRepo), parseRepoContents(curr.repos[actions.addRepo], actions.addRepo)));
result.delete.push(...parseRepoContents(prev.repos[actions.addRepo], actions.addRepo));
}
return result;
}
@@ -41422,9 +41424,6 @@ function parseRepoContents(repoContents, repository) {
};
});
}
function getDropped(oldPackages, newPackages) {
return oldPackages.filter(p => newPackages.filter(np => np.package === p.package).length === 0);
}
function isDelete(actions) {
return !!(actions.removeRepo && actions.addRepo === null);
}
@@ -41434,6 +41433,34 @@ function isAdd(actions) {
function isMove(actions) {
return !!(actions.removeRepo && actions.addRepo);
}
function getDepRepo(destination) {
const split = (destination || '').split('-');
switch (split[split.length - 1]) {
case 'testing':
case 'gremlins':
return 'testing';
case 'staging':
case 'goblins':
return 'staging';
default:
return 'stable';
}
}
function getTier(destination) {
const split = (destination || '').split('-');
switch (split[0]) {
case 'extra':
case 'world':
return '1';
case 'galaxy':
return '2';
case 'multilib':
case 'lib32':
return '3';
default:
return '0';
}
}
async function tryRead(location) {
try {
const contents = isUrl(location) ? await (await distribution.get(location)).text() : await promises_namespaceObject.readFile(location, { encoding: 'utf-8' });
@@ -41475,6 +41502,7 @@ async function main() {
if (mode === 'move') {
for (const pkg of parsedData.move) {
const filename = getFilename(pkg);
console.log(`moving ${filename} from ${parsedData.actions.removeRepo} to ${parsedData.actions.addRepo} ...`);
const files = await distribution.get(`${github.context.serverUrl}/api/v1/packages/${github.context.repo.owner}/arch/${pkg.package}/${pkg.version}/files`, { headers }).json();
const match = files.filter(f => f.name === filename);
if (match.length !== 1) {
@@ -41486,11 +41514,13 @@ async function main() {
body,
headers
});
await distribution.post(`${github.context.serverUrl}/api/v1/packages/${github.context.repo.owner}/arch/${pkg.package}/-/link/${github.context.repo.repo}`, { headers });
}
await deletePackages(parsedData.move, headers);
return;
}
else if (mode === 'delete') {
console.log(`deleting ${parsedData.delete.join(', ') || 'no packages'} ...`);
await deletePackages(parsedData.delete, headers);
return;
}
@@ -41513,11 +41543,14 @@ async function doParse() {
const previous = core.getInput('previous', { required: true });
const current = getCurrent();
const diff = await parse(previous, current);
console.log(diff);
core.setOutput('parsed-data', JSON.stringify(diff));
core.setOutput('build', diff.build);
core.setOutput('move', diff.move.length > 0);
core.setOutput('delete', diff.delete.length > 0);
core.setOutput('destination', diff.actions.addRepo);
core.setOutput('deps', diff.deps);
core.setOutput('tier', diff.tier);
}
//# sourceMappingURL=router.js.map
;// CONCATENATED MODULE: ./lib/src/index.js

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "pkgbase-yaml-parser",
"version": "0.0.1",
"version": "1.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "pkgbase-yaml-parser",
"version": "0.0.1",
"version": "1.0.3",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.11.1",

View File

@@ -1,6 +1,6 @@
{
"name": "pkgbase-yaml-parser",
"version": "0.0.1",
"version": "1.0.3",
"description": "compare Artix `pkgbase.yaml` files",
"keywords": [
"artix",

View File

@@ -1,9 +1,10 @@
import { type PathLike } from 'fs';
import fsp from 'fs/promises';
import { URL } from 'url';
import ky from 'ky';
import * as YAML from 'yaml';
export type DependencyRepo = 'stable' | 'testing' | 'staging';
export interface PackageInfo {
package: string;
repository: string;
@@ -25,6 +26,8 @@ export interface Result {
build: boolean;
move: PackageInfo[];
delete: PackageInfo[];
deps: DependencyRepo;
tier: string;
actions: Actions;
}
@@ -61,6 +64,8 @@ export async function parse(previous: string, current: string): Promise<Result>
build: false,
move: [],
delete: [],
deps: getDepRepo(actions.addRepo),
tier: getTier(actions.addRepo || actions.removeRepo),
actions,
};
@@ -70,11 +75,11 @@ export async function parse(previous: string, current: string): Promise<Result>
result.delete.push(...parseRepoContents(repo, actions.removeRepo));
}
else if (isMove(actions)) {
const moving = result.move = parseRepoContents(curr.repos[actions.addRepo], actions.removeRepo);
prev && result.delete.push(...getDropped(parseRepoContents(prev.repos[actions.addRepo], actions.addRepo), moving));
result.move = parseRepoContents(curr.repos[actions.addRepo], actions.removeRepo);
prev && result.delete.push(...parseRepoContents(prev.repos[actions.addRepo], actions.addRepo));
}
else if ((result.build = isAdd(actions)) && prev) {
result.delete.push(...getDropped(parseRepoContents(prev.repos[actions.addRepo], actions.addRepo), parseRepoContents(curr.repos[actions.addRepo], actions.addRepo)));
result.delete.push(...parseRepoContents(prev.repos[actions.addRepo], actions.addRepo));
}
return result;
@@ -91,10 +96,6 @@ function parseRepoContents(repoContents: RepoContents, repository: string): Pack
});
}
function getDropped(oldPackages: PackageInfo[], newPackages: PackageInfo[]): PackageInfo[] {
return oldPackages.filter(p => newPackages.filter(np => np.package === p.package).length === 0);
}
function isDelete(actions: Actions): boolean {
return !!(actions.removeRepo && actions.addRepo === null);
}
@@ -107,6 +108,36 @@ function isMove(actions: Actions): boolean {
return !!(actions.removeRepo && actions.addRepo);
}
export function getDepRepo(destination: string): DependencyRepo {
const split = (destination || '').split('-');
switch(split[split.length - 1]) {
case 'testing':
case 'gremlins':
return 'testing';
case 'staging':
case 'goblins':
return 'staging';
default:
return 'stable';
}
}
export function getTier(destination: string): string {
const split = (destination || '').split('-');
switch(split[0]) {
case 'extra':
case 'world':
return '1';
case 'galaxy':
return '2';
case 'multilib':
case 'lib32':
return '3';
default:
return '0';
}
}
export async function tryRead(location: string): Promise<PkgBase | null> {
try {
const contents = isUrl(location) ? await (await ky.get(location)).text() : await fsp.readFile(location, { encoding: 'utf-8' });

View File

@@ -31,6 +31,7 @@ export async function main() {
if (mode === 'move') {
for (const pkg of parsedData.move) {
const filename = getFilename(pkg);
console.log(`moving ${filename} from ${parsedData.actions.removeRepo} to ${parsedData.actions.addRepo} ...`);
const files = await ky.get(`${context.serverUrl}/api/v1/packages/${context.repo.owner}/arch/${pkg.package}/${pkg.version}/files`, { headers }).json<PackageFile[]>();
const match = files.filter(f => f.name === filename);
if (match.length !== 1) {
@@ -42,11 +43,13 @@ export async function main() {
body,
headers
});
await ky.post(`${context.serverUrl}/api/v1/packages/${context.repo.owner}/arch/${pkg.package}/-/link/${context.repo.repo}`, { headers });
}
await deletePackages(parsedData.move, headers);
return;
}
else if (mode === 'delete') {
console.log(`deleting ${parsedData.delete.join(', ') || 'no packages'} ...`);
await deletePackages(parsedData.delete, headers);
return;
}
@@ -73,9 +76,12 @@ async function doParse() {
const previous = core.getInput('previous', { required: true });
const current = getCurrent();
const diff = await parse(previous, current);
console.log(diff);
core.setOutput('parsed-data', JSON.stringify(diff));
core.setOutput('build', diff.build);
core.setOutput('move', diff.move.length > 0);
core.setOutput('delete', diff.delete.length > 0);
core.setOutput('destination', diff.actions.addRepo);
core.setOutput('deps', diff.deps);
core.setOutput('tier', diff.tier);
}

View File

@@ -1,6 +1,6 @@
import path from 'path';
import { describe, expect, it } from 'vitest';
import { parse, type Result } from '../src/pkgbase.js';
import { parse, getDepRepo, getTier, type Result } from '../src/pkgbase.js';
describe('pkgbase parser', () => {
it('can detect an add operation', async () => {
@@ -8,6 +8,8 @@ describe('pkgbase parser', () => {
build: true,
move: [],
delete: [],
deps: 'staging',
tier: '0',
actions: {
addRepo: 'system-goblins',
removeRepo: null,
@@ -27,6 +29,8 @@ describe('pkgbase parser', () => {
build: true,
move: [],
delete: [],
deps: 'stable',
tier: '1',
actions: {
addRepo: 'world',
removeRepo: null,
@@ -51,8 +55,22 @@ describe('pkgbase parser', () => {
package: "pidgin",
repository: "world",
version: "2.14.14-3",
},
{
"architecture": "x86_64",
"package": "libpurple",
"repository": "world",
"version": "2.14.14-3",
},
{
"architecture": "x86_64",
"package": "finch",
"repository": "world",
"version": "2.14.14-3",
}
],
deps: 'stable',
tier: '1',
actions: {
addRepo: 'world',
removeRepo: null,
@@ -78,7 +96,14 @@ describe('pkgbase parser', () => {
version: "1:7.9.2-1",
}
],
delete: [],
delete: [{
"architecture": "x86_64",
"package": "opencascade",
"repository": "world",
"version": "1:7.9.1-1",
}],
deps: 'stable',
tier: '1',
actions: {
addRepo: 'world',
removeRepo: 'world-gremlins',
@@ -116,8 +141,22 @@ describe('pkgbase parser', () => {
package: "pidgin",
repository: "world",
version: "2.14.14-3",
},
{
"architecture": "x86_64",
"package": "libpurple",
"repository": "world",
"version": "2.14.14-3",
},
{
"architecture": "x86_64",
"package": "finch",
"repository": "world",
"version": "2.14.14-3",
}
],
deps: 'stable',
tier: '1',
actions: {
addRepo: 'world',
removeRepo: 'world-gremlins',
@@ -129,7 +168,7 @@ describe('pkgbase parser', () => {
}
};
const rDir = 'move-with-dropped';
await expect(parse(`https://git.sanin.dev/packages_test/pkgbase-yaml-parser/raw/branch/master/test/resources/${rDir}/pkgbase.old.yaml`, path.join('test', 'resources', rDir, 'pkgbase.new.yaml'))).resolves.toEqual(expected);
await expect(parse(`https://git.sanin.dev/packages_infra/pkgbase-yaml-parser/raw/branch/master/test/resources/${rDir}/pkgbase.old.yaml`, path.join('test', 'resources', rDir, 'pkgbase.new.yaml'))).resolves.toEqual(expected);
});
it('can detect a delete operation', async () => {
@@ -156,6 +195,8 @@ describe('pkgbase parser', () => {
version: "3.13.0-2",
}
],
deps: 'stable',
tier: '1',
actions: {
addRepo: null,
removeRepo: 'world',
@@ -169,4 +210,15 @@ describe('pkgbase parser', () => {
const rDir = 'remove';
await expect(parse(path.join('test', 'resources', rDir, 'pkgbase.old.yaml'), path.join('test', 'resources', rDir, 'pkgbase.new.yaml'))).resolves.toEqual(expected);
});
it('can handle Arch repos', async () => {
expect(getDepRepo('core')).to.be.equal('stable');
expect(getDepRepo('core-testing')).to.be.equal('testing');
expect(getDepRepo('extra-staging')).to.be.equal('staging');
expect(getTier('core-testing')).to.be.equal('0');
expect(getTier('extra')).to.be.equal('1');
expect(getTier('galaxy-goblins')).to.be.equal('2');
expect(getTier('multilib')).to.be.equal('3');
expect(getTier('lib32')).to.be.equal('3');
});
});