core icon indicating copy to clipboard operation
core copied to clipboard

Investigate Title Updates Based on Labels

Open spbolton opened this issue 6 months ago • 0 comments

This is only required if we find the solution above requires the developer to remember or know the available list of actions and scopes.

Tasks:

  • Research existing solutions for updating PR titles based on labels
  • If no suitable solution exists, outline a custom GitHub Action to achieve this. Make use of AI to help.
  • Test the chosen or proposed solution in our test branch

Possible Custom Action Steps

  1. Define labels for conventional commits actions and scopes and a "breaking" label
  2. When title is created or updated pass it to a github actions workflow
  3. Extract any existing conventional commit prefix from the message using a regular expression. If there is no prefix then just use the message as is. Be aware of the posibility of colon within the message.
feat(api)!: send an email to the customer when a product is shipped
  1. create the conventional commit prefix based on the labels
  2. Recreate the title by appending the conventional commit prefix to the message.
  • Be aware of the possibility that auto-updating the title could trigger the same action to be triggered. An unvalidated AI example of this task is provided below
name: Update PR Title Based on Labels

on:
  pull_request:
    types: [opened, edited, labeled, unlabeled]

jobs:
  update-title:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/github-script@v6
        with:
          github-token: ${{secrets.GITHUB_TOKEN}}
          script: |
            const core = require('@actions/core');
            const github = require('@actions/github');

            async function run() {
              try {
                const { pull_request } = github.context.payload;
                
                // Get current labels
                const labelsResponse = await github.rest.issues.listLabelsOnIssue({
                  owner: github.context.repo.owner,
                  repo: github.context.repo.repo,
                  issue_number: pull_request.number,
                });
                const currentLabels = labelsResponse.data.map(label => label.name);

                // Extract type and scope from labels
                const typeLabel = currentLabels.find(label => label.startsWith('type:'));
                const scopeLabel = currentLabels.find(label => label.startsWith('scope:'));
                const isBreaking = currentLabels.includes('breaking');

                const type = typeLabel ? typeLabel.split(':')[1].trim() : null;
                const scope = scopeLabel ? scopeLabel.split(':')[1].trim() : null;

                // Extract existing title components
                const titleRegex = /^(?:(\w+)(?:\((\w+)\))?(?:!)?:)?\s*(.+)$/;
                const [, existingType, existingScope, message] = pull_request.title.match(titleRegex);

                // Prepare new title components
                const newType = type || existingType || 'chore';
                const newScope = scope || existingScope || '';
                const breakingChange = isBreaking ? '!' : '';

                // Construct new title
                const newTitle = `${newType}${newScope ? `(${newScope})` : ''}${breakingChange}: ${message}`;

                // Update PR title if it has changed
                if (newTitle !== pull_request.title) {
                  await github.rest.pulls.update({
                    owner: github.context.repo.owner,
                    repo: github.context.repo.repo,
                    pull_number: pull_request.number,
                    title: newTitle
                  });
                  console.log(`Updated PR title to: ${newTitle}`);
                } else {
                  console.log('PR title is already up to date.');
                }
              } catch (error) {
                core.setFailed(error.message);
              }
            }

            run();

Key Considerations:

  • How well does this integrate with conventional commit enforcement?
  • Does it provide a user-friendly way for developers to set types and scopes?
  • Can it automatically update the PR title when labels change?

spbolton avatar Aug 23 '24 10:08 spbolton