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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,30 @@ 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 |
Expand All @@ -85,6 +109,7 @@ steps:
| `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-sections` | JSON array defining changelog sections. Example: `[{"type":"feat","section":"Features","hidden":false}]`. Overrides config file settings for all packages. |

## 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