Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • semantic-release/bzlmod
1 result
Show changes
Commits on Source (5)
# [1.1.0](https://git.gitlab.arm.com/semantic-release/bzlmod/compare/v1.0.3...v1.1.0) (2023-11-16)
### Features
- generate `metadata.json`
([ae840de](https://git.gitlab.arm.com/semantic-release/bzlmod/commit/ae840de23660a0f9fa675294235e468965a3baf4))
## [1.0.3](https://git.gitlab.arm.com/semantic-release/bzlmod/compare/v1.0.2...v1.0.3) (2023-11-15)
### Bug Fixes
......
......@@ -10,8 +10,7 @@ A `semantic-release` plugin to update the Bazel module version specified in `MOD
## Getting Started
```sh
export GITLAB_TOKEN="<personal-access-token>"
npm install --save-dev git+https://git.gitlab.arm.com/semantic-release/bzlmod.git
npm install --save-dev https://gitlab.arm.com/semantic-release/bzlmod/-/releases/permalink/latest/downloads/package.tar.gz
```
Add the following to `.releaserc.yaml`:
......@@ -68,8 +67,7 @@ plugins:
- path: "@semantic-release/bzlmod"
source:
prefix: ${CI_PROJECT_NAME}-v${version}
archive: ${CI_PROJECT_NAME}-v${version}.tar.gz
url: ${CI_PROJECT_URL}/-/releases/v${version}/downloads/${CI_PROJECT_NAME}-v${version}.tar.gz
url: ${CI_PROJECT_URL}/-/releases/v${version}/downloads/src.tar.gz
- path: "@semantic-release/gitlab"
assets:
- path: MODULE.bazel
......@@ -78,9 +76,12 @@ plugins:
- path: source.json
type: package
filepath: /modules/${env.CI_PROJECT_NAME}/${nextRelease.version}/source.json
- path: ${env.CI_PROJECT_NAME}-v${nextRelease.version}.tar.gz
- path: src.tar.gz
type: package
filepath: /${env.CI_PROJECT_NAME}-v${nextRelease.version}.tar.gz
filepath: /src.tar.gz
- path: metadata.json
type: package
filepath: /modules/${env.CI_PROJECT_NAME}/metadata.json
```
`bzlmod` can then be pointed directly at the GitLab release to use the project. This negates the need to upload all released versions to a `bzlmod` registry.
......
{
"private": true,
"name": "@semantic-release/bzlmod",
"version": "1.0.3",
"version": "1.1.0",
"description": "A `semantic release` plugin for bzlmod",
"exports": {
"import": "./plugin.mjs",
......
......@@ -77,13 +77,15 @@ export async function verifyConditions(pluginConfig, context) {
throw new SemanticReleaseError('`source` must be a mapping', 'EBZLMODCFG', `${source} (${typeof source})`);
}
let {url, prefix, archive = 'src.tar', output = 'source.json'} = source;
let {url, prefix, archive = 'src.tar', output = 'source.json', metadata = 'metadata.json'} = source;
if (typeof url !== 'string') {
throw new SemanticReleaseError('`source.url` must be a string', 'EBZLMODCFG', `${url} (${typeof url})`);
} else if (typeof prefix !== 'string') {
throw new SemanticReleaseError('`source.prefix` must be a string', 'EBZLMODCFG', `${prefix} (${typeof prefix})`);
} else if (typeof archive !== 'string') {
throw new SemanticReleaseError('`source.archive` must be a string', 'EBZLMODCFG', `${archive} (${typeof archive})`);
} else if (typeof metadata !== 'string') {
throw new SemanticReleaseError('`source.metadata` must be a string', 'EBZLMODCFG', `${metadata} (${typeof metadata})`);
} else if (typeof output !== 'string') {
throw new SemanticReleaseError('`source.output` must be a string', 'EBZLMODCFG', `${output} (${typeof output})`);
}
......@@ -113,6 +115,12 @@ export async function verifyConditions(pluginConfig, context) {
throw new SemanticReleaseError('`source.archive` has unsupported extension', 'EBZLMODCFG', `${extension(archive)} not in ${Object.keys(COMPRESSION).join(', ')}`);
}
try {
metadata = template(metadata)(ctx);
} catch (error) {
throw new SemanticReleaseError('`source.metadata` failed to be templated', 'EBZLMODCFG', `${error}`);
}
try {
output = template(output)(ctx);
} catch (error) {
......@@ -138,6 +146,9 @@ export async function verifyConditions(pluginConfig, context) {
logger.success('Validated `source` configuration');
logger.info('`source.prefix` is `%s`', prefix);
logger.info('`source.url` is `%s`', url);
logger.info('`source.output` is `%s`', output);
logger.info('`source.archive` is `%s`', archive);
logger.info('`source.metadata` is `%s`', metadata);
}
export async function prepare(pluginConfig, context) {
......@@ -169,13 +180,20 @@ export async function prepare(pluginConfig, context) {
return;
}
let {url, prefix, output = 'source.json', archive = 'src.tar'} = source;
let {
url,
prefix,
output = 'source.json',
archive = 'src.tar',
metadata = 'metadata.json',
} = source;
const ctx = {...env, version, env, nextRelease: {version}};
prefix = path.normalize(template(prefix)(ctx));
url = new URL(template(url)(ctx));
output = path.join(cwd, template(output)(ctx));
archive = path.join(cwd, template(archive)(ctx));
metadata = path.join(cwd, template(metadata)(ctx));
const ext = extension(archive);
const format = ext.startsWith('.tar') ? 'tar' : 'zip';
......@@ -196,7 +214,13 @@ export async function prepare(pluginConfig, context) {
strip_prefix: prefix, // eslint-disable-line camelcase
};
await writeFile(output, JSON.stringify(src));
logger.success('Wrote `%s`', output);
logger.info('`%j`', src);
const meta = {
versions: [version],
};
await writeFile(metadata, JSON.stringify(meta));
logger.success('Wrote `%s`', output);
logger.info('`%j`', meta);
}
......@@ -9,7 +9,6 @@ import {temporaryDirectory} from 'tempy';
import git from 'isomorphic-git';
import which from 'which';
import ssri from 'ssri';
import {template} from 'lodash-es';
test.beforeEach(async t => {
clearModule('../plugin.mjs');
......@@ -19,6 +18,8 @@ test.beforeEach(async t => {
const dir = temporaryDirectory();
t.context.source = path.join(dir, 'source.json');
t.context.archive = path.join(dir, 'archive.tar');
t.context.metadata = path.join(dir, 'metadata.json');
t.context.touch = path.join(dir, 'touch.txt');
await writeFile(t.context.touch, 'Hello, world!');
......@@ -43,8 +44,9 @@ test.beforeEach(async t => {
source: {
url: '${HOST}/there/${nextRelease.version}', // eslint-disable-line no-template-curly-in-string
prefix: '${PROJECT}-${nextRelease.version}', // eslint-disable-line no-template-curly-in-string
archive: '${PROJECT}-${nextRelease.version}.tar', // eslint-disable-line no-template-curly-in-string
output: path.relative(dir, t.context.source),
archive: path.relative(dir, t.context.archive),
metadata: path.relative(dir, t.context.metadata),
},
};
t.context.ctx = {
......@@ -130,6 +132,10 @@ test('Throws `EBZLMODCFG` error when `source.archive` must be a string', failure
t.context.cfg.source.archive = 1;
});
test('Throws `EBZLMODCFG` error when `source.metadata` must be a string', failure, async t => {
t.context.cfg.source.metadata = 1;
});
test('Throws `EBZLMODCFG` error when `source.output` must be a string', failure, async t => {
t.context.cfg.source.output = 1;
});
......@@ -158,6 +164,10 @@ test('Throws `EBZLMODCFG` error when `source.archive` has unsupported extension'
t.context.cfg.source.archive += '.abc';
});
test('Throws `EBZLMODCFG` error when `source.metadata` failed to be templated', failure, async t => {
t.context.cfg.source.metadata += '${NOPE}'; // eslint-disable-line no-template-curly-in-string
});
test('Throws `EBZLMODCFG` error when `source.prefix` failed to be templated', failure, async t => {
delete t.context.ctx.env.PROJECT;
});
......@@ -174,19 +184,18 @@ test('Throws `EBZLMODCFG` error when failed to run `.+` CLI', failure, async t =
for (const extension of ['.tar', '.zip', '.tar.gz']) {
(which.sync('git') ? test : test.skip)(`Verify and prepare the package${extension}`, success, async t => {
t.context.cfg.source.archive = t.context.cfg.source.archive.replace('.tar', extension);
t.context.archive = t.context.archive.replace('.tar', extension);
}, async t => {
const data = await readFile(t.context.source);
const json = JSON.parse(data);
t.is(typeof json.url, 'string');
t.is(typeof json.integrity, 'string');
t.is(typeof json.strip_prefix, 'string');
const {env, cwd, nextRelease: {version}} = t.context.ctx;
const ctx = {...env, version, env, nextRelease: {version}};
const {archive} = t.context.cfg.source;
const tarPath = path.join(cwd, template(archive)(ctx));
const tarStream = fs.createReadStream(tarPath);
const integrity = await ssri.fromStream(tarStream);
t.is(integrity.toString(), json.integrity);
const source = JSON.parse(await readFile(t.context.source));
t.is(typeof source.url, 'string');
t.is(typeof source.integrity, 'string');
t.is(typeof source.strip_prefix, 'string');
const archive = fs.createReadStream(t.context.archive);
const integrity = await ssri.fromStream(archive);
t.is(integrity.toString(), source.integrity);
const metadata = JSON.parse(await readFile(t.context.metadata));
const {nextRelease: {version}} = t.context.ctx;
t.deepEqual(metadata.versions, [version]);
});
}
......@@ -201,3 +210,7 @@ test('Verify and prepare the package when no `source.output`', success, async t
test('Verify and prepare the package when no `source.archive`', success, async t => {
delete t.context.cfg.source.archive;
});
test('Verify and prepare the package when no `source.metadata`', success, async t => {
delete t.context.cfg.source.metadata;
});