-
Notifications
You must be signed in to change notification settings - Fork 4
Add docs-changelog-commit and docs-changelog-generate workflows and accompanying actions #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
0e7290a
490dab8
0f5eeb2
feba56f
e90995f
252a590
583ba51
60ebc8a
26b0adf
2966964
116c92f
199da2d
38575bc
5a7f7ce
dce6d29
d8faffe
5f06856
981d2f8
b86ad95
2e7371a
f9a6523
7385214
9e55057
b723a0c
aad75f3
d424f92
76f2baa
5daa6d1
a48024a
8028d84
fa5cce5
a67c45a
1d925fa
dd9ba2d
9d79b3c
c7f963e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| name: Changelog commit | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| run-id: | ||
| description: 'Workflow run ID to download the changelog artifact from' | ||
| type: string | ||
| required: true | ||
| comment-only: | ||
| description: 'Post changelog as a PR comment instead of committing to the branch' | ||
| type: boolean | ||
| default: false | ||
|
|
||
| concurrency: | ||
| group: changelog-commit-${{ github.event.workflow_run.head_branch || github.run_id }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| commit: | ||
| if: github.event.workflow_run.event == 'pull_request' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Commit changelog | ||
| uses: elastic/docs-actions/changelog/commit@v1 | ||
| with: | ||
| run-id: ${{ inputs.run-id }} | ||
| comment-only: ${{ inputs.comment-only }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| name: Changelog | ||
|
cotti marked this conversation as resolved.
Outdated
|
||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| config: | ||
| description: 'Path to changelog.yml configuration file' | ||
| type: string | ||
| default: 'docs/changelog.yml' | ||
| strip-title-prefix: | ||
|
cotti marked this conversation as resolved.
Outdated
|
||
| description: 'Remove [Prefix]: from PR titles' | ||
| type: boolean | ||
| default: false | ||
| changelog-dir: | ||
|
cotti marked this conversation as resolved.
Outdated
|
||
| description: 'Directory for changelog entry files' | ||
| type: string | ||
| default: 'docs/changelog' | ||
| docs-builder-version: | ||
|
cotti marked this conversation as resolved.
Outdated
|
||
| description: 'docs-builder version to install' | ||
| type: string | ||
| default: 'edge' | ||
|
|
||
| concurrency: | ||
| group: changelog-${{ github.event.pull_request.number || github.run_id }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| generate: | ||
| if: github.event.pull_request.state == 'open' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Generate changelog | ||
| uses: elastic/docs-actions/changelog/generate@v1 | ||
| with: | ||
| config: ${{ inputs.config }} | ||
| strip-title-prefix: ${{ inputs.strip-title-prefix }} | ||
| changelog-dir: ${{ inputs.changelog-dir }} | ||
| docs-builder-version: ${{ inputs.docs-builder-version }} | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,167 @@ | ||||||||
| # Changelog automation | ||||||||
|
|
||||||||
| Automatically generate and commit changelog entries for pull requests. | ||||||||
|
|
||||||||
| When a PR is opened or labeled, the system generates a changelog YAML file based on the PR title and type label, commits it to the PR branch, and posts a comment with a link to view or edit the entry. | ||||||||
|
|
||||||||
| ## Setup | ||||||||
|
|
||||||||
| ### 1. Add the changelog configuration | ||||||||
|
|
||||||||
| Create `docs/changelog.yml` in your repository by running `docs-builder changelog init`. | ||||||||
|
|
||||||||
| By default, you will get a file with this structure: | ||||||||
|
|
||||||||
| ```yaml | ||||||||
| pivot: | ||||||||
| types: | ||||||||
| enhancement: | ||||||||
| labels: | ||||||||
| - enhancement | ||||||||
| - feature | ||||||||
| bug: | ||||||||
| labels: | ||||||||
| - bug | ||||||||
| breaking: | ||||||||
| labels: | ||||||||
| - breaking | ||||||||
| deprecation: | ||||||||
| labels: | ||||||||
| - deprecation | ||||||||
| ``` | ||||||||
|
|
||||||||
| Each key under `pivot.types` is a changelog type. The `labels` list defines which GitHub labels map to that type. When a PR has one of these labels, the changelog entry is categorized accordingly. | ||||||||
|
|
||||||||
| ### 2. Create the workflow | ||||||||
|
|
||||||||
| Add the following: | ||||||||
|
|
||||||||
| **`.github/workflows/changelog-generate.yml`** | ||||||||
|
|
||||||||
| ```yaml | ||||||||
| name: changelog-generate | ||||||||
|
|
||||||||
| on: | ||||||||
| pull_request: | ||||||||
| types: | ||||||||
| - opened | ||||||||
| - synchronize | ||||||||
| - reopened | ||||||||
| - edited | ||||||||
| - labeled | ||||||||
| - unlabeled | ||||||||
|
|
||||||||
| permissions: | ||||||||
| contents: read | ||||||||
|
|
||||||||
| jobs: | ||||||||
| generate: | ||||||||
| uses: elastic/docs-actions/.github/workflows/changelog-generate.yml@v1 | ||||||||
| ``` | ||||||||
|
|
||||||||
| **`.github/workflows/changelog-commit.yml`** | ||||||||
|
|
||||||||
| ```yaml | ||||||||
| name: changelog-commit | ||||||||
|
|
||||||||
| on: | ||||||||
| workflow_run: | ||||||||
| workflows: [changelog-generate] | ||||||||
| types: | ||||||||
| - completed | ||||||||
|
|
||||||||
| permissions: | ||||||||
| actions: read | ||||||||
| contents: write | ||||||||
| pull-requests: write | ||||||||
|
|
||||||||
| jobs: | ||||||||
|
cotti marked this conversation as resolved.
|
||||||||
| commit: | ||||||||
| uses: elastic/docs-actions/.github/workflows/changelog-commit.yml@v1 | ||||||||
| with: | ||||||||
| run-id: ${{ github.event.workflow_run.id }} | ||||||||
| ``` | ||||||||
|
|
||||||||
| > **Important:** The `name` in the generate workflow (`changelog-generate`) must match the `workflows:` reference in the commit workflow. If you rename one, rename the other. | ||||||||
|
|
||||||||
| The two-workflow design is required because the generate workflow runs with read-only permissions (from the PR context), while the commit workflow runs with write permissions (from `workflow_run`, which uses the base branch's permissions). This is a [standard pattern](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) for safely writing to PR branches from forks. | ||||||||
|
|
||||||||
| ### 3. Create the labels | ||||||||
|
|
||||||||
| Make sure the GitHub labels referenced in your `docs/changelog.yml` exist in your repository. You also need a `changelog:skip` label for PRs that should not generate a changelog entry. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
At the moment, we can refer them to https://elastic.github.io/docs-builder/contribute/changelog/#rules-for-creation-and-publishing for more info, though I'm updating that path in one of my outstanding PRs. |
||||||||
|
|
||||||||
| ## How it works | ||||||||
|
|
||||||||
| ``` | ||||||||
| PR opened/labeled/title edited | ||||||||
| | | ||||||||
| v | ||||||||
| generate job | ||||||||
| | | ||||||||
| +-- skip if changelog:skip label is present | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per my earlier comment, this should ideally support both include/exclude rules:
Suggested change
|
||||||||
| +-- skip if last commit is from the bot (prevents loops) | ||||||||
| +-- skip if changelog file was manually edited | ||||||||
| | | ||||||||
| +-- runs: docs-builder changelog add | ||||||||
| +-- uploads result as artifact | ||||||||
| | | ||||||||
| v | ||||||||
| commit job | ||||||||
| | | ||||||||
| +-- re-validates PR state (labels, head SHA) | ||||||||
| +-- downloads artifact | ||||||||
| +-- commits changelog file to PR branch | ||||||||
| +-- posts PR comment with view/edit links | ||||||||
| ``` | ||||||||
|
|
||||||||
| ## Inputs | ||||||||
|
|
||||||||
| ### Generate workflow | ||||||||
|
|
||||||||
| | Input | Description | Default | | ||||||||
| |------------------------|------------------------------------------|----------------------| | ||||||||
| | `config` | Path to changelog configuration file | `docs/changelog.yml` | | ||||||||
| | `strip-title-prefix` | Remove `[Prefix]:` from PR titles | `false` | | ||||||||
| | `changelog-dir` | Directory for changelog entry files | `docs/changelog` | | ||||||||
| | `docs-builder-version` | docs-builder version to install | `edge` | | ||||||||
|
|
||||||||
| ### Commit workflow | ||||||||
|
|
||||||||
| | Input | Description | Default | | ||||||||
| |----------------|---------------------------------------------------------|----------| | ||||||||
| | `run-id` | Workflow run ID to download the changelog artifact from | required | | ||||||||
| | `comment-only` | Post as PR comment instead of committing to the branch | `false` | | ||||||||
|
|
||||||||
| ### Comment-only mode | ||||||||
|
|
||||||||
| If you prefer not to have bot commits on your PR branches, pass `comment-only: true` to the commit workflow. The changelog entry will be posted as a PR comment instead of being committed to the branch: | ||||||||
|
|
||||||||
| ```yaml | ||||||||
| jobs: | ||||||||
| commit: | ||||||||
| uses: elastic/docs-actions/.github/workflows/changelog-commit.yml@v1 | ||||||||
| with: | ||||||||
| run-id: ${{ github.event.workflow_run.id }} | ||||||||
| comment-only: true | ||||||||
| ``` | ||||||||
|
|
||||||||
| ## Skipping changelog generation | ||||||||
|
|
||||||||
| Add the `changelog:skip` label to a PR to skip changelog generation entirely. The generate action will exit early and no artifact or commit is produced. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Per my other comments, this needs to handle all the options we provide in https://elastic.github.io/docs-builder/contribute/changelog/#rules-reference |
||||||||
|
|
||||||||
| ## Manual edits | ||||||||
|
|
||||||||
| If a human edits the changelog file directly (i.e., the last commit to `docs/changelog/{PR_NUMBER}.yaml` is not from `github-actions[bot]`), the automation will not overwrite it. This lets authors customize the generated entry without it being regenerated on the next push. | ||||||||
|
cotti marked this conversation as resolved.
Outdated
|
||||||||
|
|
||||||||
| ## Output | ||||||||
|
|
||||||||
| Each PR produces a file at `docs/changelog/{PR_NUMBER}.yaml` on the PR branch. These files are consumed by `docs-builder` during documentation builds to produce a rendered changelog page. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Per Martijn's comments elsewhere, I think this needs to accommodate the different file output names (https://elastic.github.io/docs-builder/contribute/changelog/#filenames) and file output directories (per config file). IMO we should expect them to have those choices defined in the config file rather than trying to support via command options.
cotti marked this conversation as resolved.
Outdated
|
||||||||
|
|
||||||||
| ## Advanced: using composite actions directly | ||||||||
|
|
||||||||
| The reusable workflows are thin wrappers around two composite actions. If you need more control, you can use them directly in your own workflow steps: | ||||||||
|
|
||||||||
| - `elastic/docs-actions/changelog/generate@v1` -- generates the changelog and uploads an artifact | ||||||||
| - `elastic/docs-actions/changelog/commit@v1` -- downloads the artifact and commits or comments | ||||||||
|
|
||||||||
| See the individual action files for their full input/output definitions. | ||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| name: changelog/commit | ||
| description: > | ||
| Download a changelog artifact from a generate workflow run, | ||
| commit it to the PR branch (or post as comment), and update the PR. | ||
|
|
||
| inputs: | ||
| run-id: | ||
| description: 'Workflow run ID to download the changelog artifact from' | ||
| default: '${{ github.run_id }}' | ||
| github-token: | ||
| description: 'GitHub token with contents:write and pull-requests:write' | ||
| default: '${{ github.token }}' | ||
| artifact-name: | ||
|
cotti marked this conversation as resolved.
Outdated
|
||
| description: 'Name of the artifact to download' | ||
| default: 'changelog-result' | ||
| comment-only: | ||
| description: 'Post changelog as a PR comment instead of committing to the branch' | ||
| default: 'false' | ||
|
|
||
| outputs: | ||
| committed: | ||
| description: 'Whether a changelog was committed (true/false)' | ||
| value: ${{ steps.commit.outputs.committed || 'false' }} | ||
| pr-number: | ||
| description: 'The PR number from the changelog metadata' | ||
| value: ${{ steps.evaluate.outputs.pr-number }} | ||
|
|
||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Download artifact | ||
| id: download | ||
| continue-on-error: true | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: ${{ inputs.artifact-name }} | ||
| path: /tmp/changelog-result | ||
| run-id: ${{ inputs.run-id }} | ||
| github-token: ${{ inputs.github-token }} | ||
|
|
||
| - name: Evaluate artifact and validate PR | ||
| id: evaluate | ||
| if: steps.download.outcome == 'success' | ||
| uses: actions/github-script@v8 | ||
| env: | ||
| COMMENT_ONLY: ${{ inputs.comment-only }} | ||
| with: | ||
| github-token: ${{ inputs.github-token }} | ||
| script: | | ||
| const script = require('${{ github.action_path }}/scripts/evaluate.js'); | ||
| await script({ github, context, core }); | ||
|
|
||
| - name: Checkout PR branch | ||
| if: steps.evaluate.outputs.should-commit == 'true' | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ steps.evaluate.outputs.head-ref }} | ||
| token: ${{ inputs.github-token }} | ||
| persist-credentials: true | ||
|
|
||
| - name: Commit changelog | ||
| if: steps.evaluate.outputs.should-commit == 'true' | ||
| id: commit | ||
| shell: bash | ||
| env: | ||
| PR_NUMBER: ${{ steps.evaluate.outputs.pr-number }} | ||
| CHANGELOG_DIR: ${{ steps.evaluate.outputs.changelog-dir }} | ||
| run: | | ||
| CHANGELOG_FILE="$CHANGELOG_DIR/${PR_NUMBER}.yaml" | ||
|
|
||
| if [ -f "$CHANGELOG_FILE" ]; then | ||
| VERB="Update" | ||
| else | ||
| VERB="Add" | ||
| fi | ||
|
|
||
| mkdir -p "$CHANGELOG_DIR" | ||
| cp "/tmp/changelog-result/${PR_NUMBER}.yaml" "$CHANGELOG_FILE" | ||
|
|
||
| git config user.name "github-actions[bot]" | ||
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | ||
| git add "$CHANGELOG_FILE" | ||
|
|
||
| if git diff --cached --quiet; then | ||
| echo "No changes to commit" | ||
| echo "committed=false" >> "$GITHUB_OUTPUT" | ||
| else | ||
| git commit -m "${VERB} changelog for PR #${PR_NUMBER}" | ||
| git push | ||
| echo "committed=true" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - name: Post success comment | ||
| if: steps.commit.outputs.committed == 'true' | ||
| uses: actions/github-script@v8 | ||
| env: | ||
| PR_NUMBER: ${{ steps.evaluate.outputs.pr-number }} | ||
| HEAD_REF: ${{ steps.evaluate.outputs.head-ref }} | ||
| CHANGELOG_DIR: ${{ steps.evaluate.outputs.changelog-dir }} | ||
| with: | ||
| github-token: ${{ inputs.github-token }} | ||
| script: | | ||
| const script = require('${{ github.action_path }}/scripts/post-success-comment.js'); | ||
| await script({ github, context, core }); | ||
|
|
||
| - name: Post comment-only changelog | ||
| if: steps.evaluate.outputs.should-comment-success == 'true' | ||
| uses: actions/github-script@v8 | ||
| env: | ||
| PR_NUMBER: ${{ steps.evaluate.outputs.pr-number }} | ||
| CHANGELOG_DIR: ${{ steps.evaluate.outputs.changelog-dir }} | ||
| with: | ||
| github-token: ${{ inputs.github-token }} | ||
| script: | | ||
| const script = require('${{ github.action_path }}/scripts/post-comment-only.js'); | ||
| await script({ github, context, core }); | ||
|
|
||
| - name: Post failure comment with available labels | ||
| if: steps.evaluate.outputs.should-comment-failure == 'true' | ||
| uses: actions/github-script@v8 | ||
| env: | ||
| PR_NUMBER: ${{ steps.evaluate.outputs.pr-number }} | ||
| LABEL_TABLE: ${{ steps.evaluate.outputs.label-table }} | ||
| CONFIG_FILE: ${{ steps.evaluate.outputs.config-file }} | ||
| with: | ||
| github-token: ${{ inputs.github-token }} | ||
| script: | | ||
| const script = require('${{ github.action_path }}/scripts/post-failure-comment.js'); | ||
| await script({ github, context, core }); | ||
Uh oh!
There was an error while loading. Please reload this page.