Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 46 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,28 +66,54 @@ steps:
manifest-file: .release-please-manifest.json
```

### Customizing Changelog Sections

You can customize the changelog sections from the workflow level, which is useful for
reusable workflows that need to enforce consistent changelog formatting across multiple
repositories:

```yaml
steps:
- uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.MY_RELEASE_PLEASE_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# optional. override changelog sections for all packages
changelog-sections: |
[
{"type":"feat","section":"🚀 Features","hidden":false},
{"type":"fix","section":"🐞 Bug Fixes","hidden":false},
{"type":"perf","section":"✨ Performance","hidden":false},
{"type":"docs","section":"📚 Documentation","hidden":false},
{"type":"chore","section":"🧰 Maintenance","hidden":true}
]
```

## Action Inputs

| input | description |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `token` | A GitHub secret token, the action defaults to using the special `secrets.GITHUB_TOKEN` |
| `release-type` | If specified, defines the release strategy to use for the repository. Reference [Release types supported](#release-types-supported) |
| `path` | create a release from a path other than the repository's root |
| `target-branch` | branch to open pull release PR against (detected by default) |
| `config-file` | Path to the release-please config in the repository. Defaults to `release-please-config.json` |
| `manifest-file` | Path to the release-please versions manifest. Defaults to `.release-please-manifest.json` |
| `repo-url` | GitHub repository name in the form of `<owner>/<repo>`. Defaults to the repository the action is running in. |
| `github-api-url` | Override the GitHub API URL. |
| `github-graphql-url` | Override the GitHub GraphQL URL |
| `fork` | If `true`, send the PR from a fork. This requires the `token` to be a user that can create forks (e.g. not the default `GITHUB_TOKEN`) |
| `include-component-in-tag` | If true, add prefix to tags and branches, allowing multiple libraries to be released from the same repository |
| `proxy-server` | Configure a proxy server in the form of `<host>:<port>` e.g. `proxy-host.com:8080` |
| `skip-github-release` | If `true`, do not attempt to create releases. This is useful if splitting release tagging from PR creation. |
| `skip-github-pull-request` | If `true`, do not attempt to create release pull requests. This is useful if splitting release tagging from PR creation. |
| `skip-labeling` | If `true`, do not attempt to label the PR. |
| `changelog-host` | The proto://host where commits live. Defaults to `${{ github.server_url }}` (usually `https://github.com`) |
| `versioning-strategy` | The versioning strategy to use. Defaults to `default` |
| `release-as` | The version to release as. |
| input | description |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `token` | A GitHub secret token, the action defaults to using the special `secrets.GITHUB_TOKEN` |
| `release-type` | If specified, defines the release strategy to use for the repository. Reference [Release types supported](#release-types-supported) |
| `path` | create a release from a path other than the repository's root |
| `target-branch` | branch to open pull release PR against (detected by default) |
| `config-file` | Path to the release-please config in the repository. Defaults to `release-please-config.json` |
| `manifest-file` | Path to the release-please versions manifest. Defaults to `.release-please-manifest.json` |
| `repo-url` | GitHub repository name in the form of `<owner>/<repo>`. Defaults to the repository the action is running in. |
| `github-api-url` | Override the GitHub API URL. |
| `github-graphql-url` | Override the GitHub GraphQL URL |
| `fork` | If `true`, send the PR from a fork. This requires the `token` to be a user that can create forks (e.g. not the default `GITHUB_TOKEN`) |
| `include-component-in-tag` | If true, add prefix to tags and branches, allowing multiple libraries to be released from the same repository |
| `proxy-server` | Configure a proxy server in the form of `<host>:<port>` e.g. `proxy-host.com:8080` |
| `skip-github-release` | If `true`, do not attempt to create releases. This is useful if splitting release tagging from PR creation. |
| `skip-github-pull-request` | If `true`, do not attempt to create release pull requests. This is useful if splitting release tagging from PR creation. |
| `skip-labeling` | If `true`, do not attempt to label the PR. |
| `changelog-host` | The proto://host where commits live. Defaults to `${{ github.server_url }}` (usually `https://github.com`) |
| `changelog-sections` | JSON array defining changelog sections. Example: `[{"type":"feat","section":"Features","hidden":false}]`. Overrides config file settings for all packages. |
| `versioning-strategy` | The versioning strategy to use. Defaults to `default` |
| `release-as` | The version to release as. |


## GitHub Credentials

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ inputs:
description: 'The version to release as.'
required: false
default: ''
changelog-sections:
description: 'JSON formatted changelog sections configuration. Example: [{"type":"feat","section":"Features","hidden":false}]'
required: false
default: ''
runs:
using: 'node20'
main: 'dist/index.js'
88 changes: 68 additions & 20 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@
// limitations under the License.

import * as core from '@actions/core';
import {GitHub, Manifest, CreatedRelease, PullRequest, VERSION} from 'release-please';
import {
GitHub,
Manifest,
CreatedRelease,
PullRequest,
VERSION,
ChangelogSection,
} from 'release-please';

const DEFAULT_CONFIG_FILE = 'release-please-config.json';
const DEFAULT_MANIFEST_FILE = '.release-please-manifest.json';
Expand Down Expand Up @@ -45,11 +52,12 @@ interface ActionInputs {
changelogHost: string;
versioningStrategy?: string;
releaseAs?: string;
changelogSections?: ChangelogSection[];
}

function parseInputs(): ActionInputs {
const inputs: ActionInputs = {
token: core.getInput('token', {required: true}),
token: core.getInput('token', { required: true }),
releaseType: getOptionalInput('release-type'),
path: getOptionalInput('path'),
repoUrl: core.getInput('repo-url') || process.env.GITHUB_REPOSITORY || '',
Expand All @@ -69,6 +77,9 @@ function parseInputs(): ActionInputs {
changelogHost: core.getInput('changelog-host') || DEFAULT_GITHUB_SERVER_URL,
versioningStrategy: getOptionalInput('versioning-strategy'),
releaseAs: getOptionalInput('release-as'),
changelogSections: parseChangelogSections(
getOptionalInput('changelog-sections'),
),
};
return inputs;
}
Expand All @@ -85,9 +96,28 @@ function getOptionalBooleanInput(name: string): boolean | undefined {
return core.getBooleanInput(name);
}

function parseChangelogSections(
input?: string,
): ChangelogSection[] | undefined {
if (!input) {
return undefined;
}
try {
const parsed = JSON.parse(input);
if (!Array.isArray(parsed)) {
core.warning('changelog-sections must be a JSON array');
return undefined;
}
return parsed;
} catch (error) {
core.warning(`Failed to parse changelog-sections: ${error}`);
return undefined;
}
}

function loadOrBuildManifest(
github: GitHub,
inputs: ActionInputs
inputs: ActionInputs,
): Promise<Manifest> {
if (inputs.releaseType) {
core.debug('Building manifest from config');
Expand All @@ -100,41 +130,56 @@ function loadOrBuildManifest(
changelogHost: inputs.changelogHost,
versioning: inputs.versioningStrategy,
releaseAs: inputs.releaseAs,
changelogSections: inputs.changelogSections,
},
{
fork: inputs.fork,
skipLabeling: inputs.skipLabeling,
},
inputs.path
inputs.path,
);
}
const manifestOverrides = inputs.fork || inputs.skipLabeling
? {
fork: inputs.fork,
skipLabeling: inputs.skipLabeling,
}
: {};
const manifestOverrides =
inputs.fork || inputs.skipLabeling
? {
fork: inputs.fork,
skipLabeling: inputs.skipLabeling,
}
: {};
core.debug('Loading manifest from config file');
return Manifest.fromManifest(
github,
github.repository.defaultBranch,
inputs.configFile,
inputs.manifestFile,
manifestOverrides
).then(manifest => {
manifestOverrides,
).then((manifest) => {
// Override changelogHost for all paths if provided as action input and different from default
if (inputs.changelogHost && inputs.changelogHost !== DEFAULT_GITHUB_SERVER_URL) {
if (
inputs.changelogHost &&
inputs.changelogHost !== DEFAULT_GITHUB_SERVER_URL
) {
core.debug(`Overriding changelogHost to: ${inputs.changelogHost}`);
for (const path in manifest.repositoryConfig) {
manifest.repositoryConfig[path].changelogHost = inputs.changelogHost;
}
}
// Override changelogSections for all paths if provided as action input
if (inputs.changelogSections) {
core.debug(
`Overriding changelogSections with ${inputs.changelogSections.length} sections`,
);
for (const path in manifest.repositoryConfig) {
manifest.repositoryConfig[path].changelogSections =
inputs.changelogSections;
}
}
return manifest;
});
}

export async function main(fetchOverride?: any) {
core.info(`Running release-please version: ${VERSION}`)
core.info(`Running release-please version: ${VERSION}`);
const inputs = parseInputs();
const github = await getGitHubInstance(inputs, fetchOverride);

Expand All @@ -151,7 +196,10 @@ export async function main(fetchOverride?: any) {
}
}

function getGitHubInstance(inputs: ActionInputs, fetchOverride?: any): Promise<GitHub> {
function getGitHubInstance(
inputs: ActionInputs,
fetchOverride?: any,
): Promise<GitHub> {
const [owner, repo] = inputs.repoUrl.split('/');
let proxy: Proxy | undefined = undefined;
if (inputs.proxyServer) {
Expand Down Expand Up @@ -184,7 +232,7 @@ function setPathOutput(path: string, key: string, value: string | boolean) {
}

function outputReleases(releases: (CreatedRelease | undefined)[]) {
releases = releases.filter(release => release !== undefined);
releases = releases.filter((release) => release !== undefined);
const pathsReleased = [];
core.setOutput('releases_created', releases.length > 0);
if (releases.length) {
Expand Down Expand Up @@ -217,7 +265,7 @@ function outputReleases(releases: (CreatedRelease | undefined)[]) {
}

function outputPRs(prs: (PullRequest | undefined)[]) {
prs = prs.filter(pr => pr !== undefined);
prs = prs.filter((pr) => pr !== undefined);
core.setOutput('prs_created', prs.length > 0);
if (prs.length) {
core.setOutput('pr', prs[0]);
Expand All @@ -226,7 +274,7 @@ function outputPRs(prs: (PullRequest | undefined)[]) {
}

if (require.main === module) {
main().catch(err => {
core.setFailed(`release-please failed: ${err.message}`)
})
main().catch((err) => {
core.setFailed(`release-please failed: ${err.message}`);
});
}
Loading