Skip to content

Commit

Permalink
feat: allow to publish to Open VSX only (#488)
Browse files Browse the repository at this point in the history
Signed-off-by: dankeboy36 <dankeboy36@gmail.com>
Co-authored-by: Felipe Santos <felipecassiors@gmail.com>
  • Loading branch information
dankeboy36 and felipecrs committed Jul 11, 2023
1 parent 03b0293 commit 28338a6
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 115 deletions.
69 changes: 47 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
[![peerDependencies](https://david-dm.org/felipecrs/semantic-release-vsce/peer-status.svg)](https://david-dm.org/felipecrs/semantic-release-vsce?type=peer)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

| Step | Description |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verify` | Verify the presence and the validity of the authentication (set via [environment variables](#environment-variables)) and the `package.json` |
| `prepare` | Generate the `.vsix` file using vsce, this can be be controlled by providing `packageVsix` in config. <br/> _Note: If the `OVSX_PAT` environment variable is set, this step will run even if not explicitly enabled_ |
| `publish` | Publish the extension |
| Step | Description |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verify` | Verify the `package.json` and the validity of the personal access tokens against Visual Studio Marketplace and/or Open VSX Registry when publish is enabled |
| `prepare` | Generate the `.vsix` file using `vsce` (can be be controlled by the [`packageVsix` config option](#packagevsix) |
| `publish` | Publish the extension to Visual Studio Marketplace and/or Open VSX Registry (learn more [here](#publishing)) |

## Install

Expand Down Expand Up @@ -60,7 +60,7 @@ The plugin can be configured in the [**semantic-release** configuration file](ht

### `packageVsix`

Whether to package or not the extension `.vsix`, or where to place it. This controls if `vsce package` gets called or not, and what value will be used for `vsce package --out`.
Whether to package or not the extension into a `.vsix` file, or where to place it. This controls if `vsce package` gets called or not, and what value will be used for `vsce package --out`.

| Value | Description |
| ------------------ | ------------------------------------------------------------------------------------------------------------ |
Expand All @@ -71,12 +71,12 @@ Whether to package or not the extension `.vsix`, or where to place it. This cont

### `publish`

Whether to publish or not the extension to Visual Studio Marketplace or OpenVSX (if the `OVSX_PAT` environment variable is present). This controls if `vsce publish` or `ovsx publish` (if the `OVSX_PAT` environment variable is present) gets called or not.
Whether to publish or not the extension to Visual Studio Marketplace and/or to Open VSX Registry. This controls if `vsce publish` or `ovsx publish` gets called or not. Learn more [here](#publishing).

| Value | Description |
| ---------------- | -------------------------------------------------------------- |
| `true` (default) | publishes the extension to Visual Studio Marketplace |
| `false` | disables publishing the extension to Visual Studio Marketplace |
| Value | Description |
| ---------------- | ------------------------------------------------------------------------------------------ |
| `true` (default) | publishes the extension to Visual Studio Marketplace and/or to Open VSX Registry |
| `false` | disables publishing the extension to Visual Studio Marketplace and/or to Open VSX Registry |

### `publishPackagePath`

Expand All @@ -90,11 +90,13 @@ Which `.vsix` file (or files) to publish. This controls what value will be used

### Environment variables

The following environment variables are supported by this plugin:

| Variable | Description |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VSCE_PAT` | **Required** (unless `publish` is set to `false`). The personal access token to publish the extension to Visual Studio Marketplace |
| `OVSX_PAT` | _Optional_. The personal access token to push to Open VSX Registry |
| `VSCE_PAT` | _Optional_. The personal access token to publish to Visual Studio Marketplace |
| `VSCE_TARGET` | _Optional_. The target to use when packaging or publishing the extension (used as `vsce package --target ${VSCE_TARGET}`). When set to `universal`, behave as if `VSCE_TARGET` was not set (i.e. build the universal/generic `vsix`). See [the platform-specific example](#platform-specific-on-github-actions) |
| `OVSX_PAT` | _Optional_. The personal access token to push to OpenVSX |

### Configuring `vsce`

Expand All @@ -104,7 +106,7 @@ You can set `vsce` options in the `package.json`, like:
// package.json
{
"vsce": {
"baseImagesUrl": "https://my.custom/base/images/url"
"baseImagesUrl": "https://my.custom/base/images/url",
"dependencies": true,
"yarn": false
}
Expand All @@ -113,19 +115,39 @@ You can set `vsce` options in the `package.json`, like:

For more information, check the [`vsce` docs](https://github.com/microsoft/vscode-vsce#configuration).

### Publishing to OpenVSX
## Publishing

This plugin can publish extensions to Visual Studio Marketplace and/or Open VSX Registry.

You can enable or disable publishing with the [`publish`](#publish) config option.

When publish is enabled (default), the plugin will publish to Visual Studio Marketplace if the `VSCE_PAT` environment variable is present, and/or to Open VSX Registry if the `OVSX_PAT` environment variable is present.

For example, you may want to disable publishing if you only want to publish the `.vsix` file as a GitHub release asset.

### Publishing to Visual Studio Marketplace

Publishing extensions to Visual Studio Marketplace using this plugin is easy:

1. Create your personal access token for Visual Studio Marketplace. Learn more [here](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token).

2. Configure the `VSCE_PAT` environment variable in your CI with the token that you created.

3. Enjoy! The plugin will automatically detect the environment variable and it will publish to Visual Studio Marketplace, no additional configuration is needed.

### Publishing to Open VSX Registry

Publishing extensions to OpenVSX using this plugin is easy:
Publishing extensions to Open VSX Registry using this plugin is easy:

1. Get a valid personal access token with the correct privileges to the publisher namespace in OpenVSX. In order to get the personal access token, check this [page](https://github.com/eclipse/openvsx/wiki).
1. Create your personal access token for Open VSX Registry. Learn more [here](https://github.com/eclipse/openvsx/wiki).

2. Configure the `OVSX_PAT` environment variable in your CI with the token that you created.

3. Enjoy! The plugin will automatically detect the environment variable and it will publish to OpenVSX, no additional configuration is needed.
3. Enjoy! The plugin will automatically detect the environment variable and it will publish to Open VSX Registry, no additional configuration is needed.

## Examples

### Github Actions
### GitHub Actions

```yaml
name: release
Expand All @@ -146,8 +168,9 @@ jobs:
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# In case you want to publish to Visual Studio Marketplace
VSCE_PAT: ${{ secrets.VSCE_PAT }}
# In case you want to publish to OpenVSX
# In case you want to publish to Open VSX Registry
OVSX_PAT: ${{ secrets.OVSX_PAT }}
```

Expand Down Expand Up @@ -277,8 +300,9 @@ jobs:
VSCE_TARGET: ${{ matrix.target }}
# All tokens are required since semantic-release needs to validate them
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# In case you want to publish to Visual Studio Marketplace
VSCE_PAT: ${{ secrets.VSCE_PAT }}
# In case you want to publish to OpenVSX
# In case you want to publish to Open VSX Registry
OVSX_PAT: ${{ secrets.OVSX_PAT }}

- uses: actions/upload-artifact@v3
Expand All @@ -303,8 +327,9 @@ jobs:
- run: npx semantic-release --extends ./publish.release.config.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# In case you want to publish to Visual Studio Marketplace
VSCE_PAT: ${{ secrets.VSCE_PAT }}
# In case you want to publish to OpenVSX
# In case you want to publish to Open VSX Registry
OVSX_PAT: ${{ secrets.OVSX_PAT }}
```

Expand Down
8 changes: 4 additions & 4 deletions lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

const execa = require('execa');
const { readJson } = require('fs-extra');
const { isOvsxEnabled, isTargetEnabled } = require('./utils');
const { isOvsxPublishEnabled, isTargetEnabled } = require('./utils');

module.exports = async (version, packageVsix, logger, cwd) => {
if (packageVsix === false) {
return;
}

const ovsxEnabled = isOvsxEnabled();
const ovsxPublishEnabled = isOvsxPublishEnabled();

if (packageVsix || ovsxEnabled) {
if (!packageVsix && ovsxEnabled) {
if (packageVsix || ovsxPublishEnabled) {
if (!packageVsix && ovsxPublishEnabled) {
logger.log(
'Packaging to VSIX even though `packageVsix` is not set as publish to OpenVSX is enabled.',
);
Expand Down
48 changes: 25 additions & 23 deletions lib/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

const execa = require('execa');
const { readJson } = require('fs-extra');
const { isOvsxEnabled, isTargetEnabled } = require('./utils');
const {
isOvsxPublishEnabled,
isTargetEnabled,
isVscePublishEnabled,
} = require('./utils');

module.exports = async (version, packagePath, logger, cwd) => {
const { publisher, name } = await readJson('./package.json');
Expand All @@ -27,38 +31,36 @@ module.exports = async (version, packagePath, logger, cwd) => {
message += ` for target ${process.env.VSCE_TARGET}`;
}
}
message += ' to Visual Studio Marketplace';
logger.log(message);

await execa('vsce', options, { stdio: 'inherit', preferLocal: true, cwd });
const releases = [];
if (isVscePublishEnabled()) {
logger.log(message + ' to Visual Studio Marketplace');

const vsceUrl = `https://marketplace.visualstudio.com/items?itemName=${publisher}.${name}`;
logger.log(`The new version is available at ${vsceUrl}.`);
await execa('vsce', options, { stdio: 'inherit', preferLocal: true, cwd });
const vsceUrl = `https://marketplace.visualstudio.com/items?itemName=${publisher}.${name}`;

const vsceRelease = {
name: 'Visual Studio Marketplace',
url: vsceUrl,
};
logger.log(`The new version is available at ${vsceUrl}.`);
releases.push({
name: 'Visual Studio Marketplace',
url: vsceUrl,
});
}

if (isOvsxEnabled()) {
logger.log('Now publishing to OpenVSX');
if (isOvsxPublishEnabled()) {
logger.log(message + 'to Open VSX Registry');

// When publishing to OpenVSX, packagePath will be always set
await execa('ovsx', options, { stdio: 'inherit', preferLocal: true, cwd });
const ovsxUrl = `https://open-vsx.org/extension/${publisher}/${name}/${version}`;

logger.log(`The new ovsx version is available at ${ovsxUrl}`);

// TODO: uncomment after https://github.com/semantic-release/semantic-release/issues/2123
// const ovsxRelease = {
// name: 'Open VSX Registry',
// url: ovsxUrl
// };

// const releases = [vsceRelease, ovsxRelease];

// return releases;
releases.push({
name: 'Open VSX Registry',
url: ovsxUrl,
});
}

return vsceRelease;
// TODO: uncomment after https://github.com/semantic-release/semantic-release/issues/2123
// return releases;
return releases.shift();
};
11 changes: 9 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
const isOvsxEnabled = () => {
// @ts-check

const isOvsxPublishEnabled = () => {
return 'OVSX_PAT' in process.env;
};

const isVscePublishEnabled = () => {
return 'VSCE_PAT' in process.env;
};

const isTargetEnabled = () => {
return (
'VSCE_TARGET' in process.env && process.env.VSCE_TARGET !== 'universal'
Expand All @@ -10,5 +16,6 @@ const isTargetEnabled = () => {

module.exports = {
isTargetEnabled,
isOvsxEnabled,
isOvsxPublishEnabled,
isVscePublishEnabled,
};
12 changes: 2 additions & 10 deletions lib/verify-ovsx-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,14 @@

const SemanticReleaseError = require('@semantic-release/error');
const execa = require('execa');
const { isOvsxEnabled } = require('./utils');

module.exports = async (logger, cwd) => {
logger.log('Verifying authentication for ovsx');

if (!isOvsxEnabled()) {
logger.log(
'Skipping verification of ovsx personal token because the `OVSX_PAT` environment variable is not set.\n\nDid you know you can easily start publishing to OpenVSX with `semantic-release-vsce`?\nLearn more at https://github.com/felipecrs/semantic-release-vsce#publishing-to-openvsx',
);
return;
}

if (!process.env.OVSX_PAT) {
throw new SemanticReleaseError(
'Empty ovsx personal access token specified.',
'EINVALIDOVSXPAT',
'Empty ovsx personal access token (`OVSX_PAT` environment variable) specified.',
'EEMPTYOVSXPAT',
);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/verify-pkg.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = async () => {

try {
packageJson = await readJson('./package.json');
} catch (error) {
} catch {
throw new SemanticReleaseError(
'The `package.json` seems to be invalid.',
'EINVALIDPKG',
Expand Down
8 changes: 4 additions & 4 deletions lib/verify-auth.js → lib/verify-vsce-auth.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// @ts-check

const execa = require('execa');
const SemanticReleaseError = require('@semantic-release/error');
const execa = require('execa');

module.exports = async (logger, cwd) => {
logger.log('Verifying authentication for vsce');

if (!process.env.VSCE_PAT) {
throw new SemanticReleaseError(
'No vsce personal access token specified (set the `VSCE_PAT` environment variable).',
'ENOVSCEPAT',
'Empty vsce personal access token (`VSCE_PAT` environment variable) specified.',
'EEMPTYVSCEPAT',
);
}

Expand All @@ -18,7 +18,7 @@ module.exports = async (logger, cwd) => {
} catch (e) {
throw new SemanticReleaseError(
`Invalid vsce personal access token. Additional information:\n\n${e}`,
'EINVALIDVSCETOKEN',
'EINVALIDVSCEPAT',
);
}
};
28 changes: 25 additions & 3 deletions lib/verify.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
// @ts-check

const SemanticReleaseError = require('@semantic-release/error');
const verifyPkg = require('./verify-pkg');
const verifyAuth = require('./verify-auth');
const verifyVsceAuth = require('./verify-vsce-auth');
const verifyOvsxAuth = require('./verify-ovsx-auth');
const verifyTarget = require('./verify-target');
const { isOvsxPublishEnabled, isVscePublishEnabled } = require('./utils');

module.exports = async (pluginConfig, { logger, cwd }) => {
await verifyPkg();
await verifyTarget();

if (pluginConfig?.publish !== false) {
await verifyAuth(logger, cwd);
await verifyOvsxAuth(logger, cwd);
const vscePublishEnabled = isVscePublishEnabled();
const ovsxPublishEnabled = isOvsxPublishEnabled();
if (!vscePublishEnabled && !ovsxPublishEnabled) {
throw new SemanticReleaseError(
'No personal access token was detected. Set the `VSCE_PAT` or the `OVSX_PAT` environment variable, at least one of them must be present when publish is enabled.\nLearn more at https://github.com/felipecrs/semantic-release-vsce#publishing',
'ENOPAT',
);
}
if (vscePublishEnabled) {
await verifyVsceAuth(logger, cwd);
} else {
logger.log(
'Skipping verification of the vsce personal access token as the `VSCE_PAT` environment variable is not set.\n\nDid you know you can easily start publishing to Visual Studio Marketplace with `semantic-release-vsce`?\nLearn more at https://github.com/felipecrs/semantic-release-vsce#publishing-to-visual-studio-marketplace',
);
}
if (ovsxPublishEnabled) {
await verifyOvsxAuth(logger, cwd);
} else {
logger.log(
'Skipping verification of the ovsx personal access token as the `OVSX_PAT` environment variable is not set.\n\nDid you know you can easily start publishing to Open VSX Registry with `semantic-release-vsce`?\nLearn more at https://github.com/felipecrs/semantic-release-vsce#publishing-to-open-vsx-registry',
);
}
}
};

0 comments on commit 28338a6

Please sign in to comment.