Skip to content
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

customize semantic-release gitlab release description #738

Open
jnschbrt opened this issue Jun 12, 2024 · 1 comment
Open

customize semantic-release gitlab release description #738

jnschbrt opened this issue Jun 12, 2024 · 1 comment

Comments

@jnschbrt
Copy link

jnschbrt commented Jun 12, 2024

I am trying to create a migration notes section for the next generated semantic-release with the help of semantic-release based on the merge-request description of the last commits.

it works with my inline-plugin to read the merge request since the last release and successfully read the migration notes.

I would now like to write these collected migration notes to the semantic-release context in order to attach them to the release created here during the ‘publish’ step of @semantic-release/gitlab.

my configuration is as follows:

/**
 * @type {import('semantic-release').GlobalConfig}
 */
module.exports = {
  branches: ["main", "master", "+([0-9])?(.{+([0-9]),x}).x"],
  ci: false,
  plugins: [
    [
      "@semantic-release/commit-analyzer",
      {
        preset: "conventionalcommits",
      },
    ],
    [
      "@semantic-release/release-notes-generator",
      {
        preset: "conventionalcommits",
      },
    ],
    [
      "@semantic-release/changelog",
      {
        changelogFile: "CHANGELOG.md",
        changelogTitle:
          "# Changelog\n\nAll notable changes to this project will be documented in this file.",
      },
    ],
    [
      "@semantic-release/git",
      {
        assets: ["CHANGELOG.md"],
        message:
          "chore(release): version ${nextRelease.version}\n\n${nextRelease.notes}",
      },
    ],
    {
      analyzeCommits: async (pluginConfig, context) => {
        const { commits, logger } = context;

        const migrationNotes = [];

        logger.log(
          `Analyzing ${commits.length} commits for migration notes...`
        );

        for (const commit of commits) {
          const subjectPattern = /Merge branch .* into 'main'/;
          const bodyPattern = /See merge request ([\w/-]+![0-9]+)/;

          // check if the commit is a merge commit
          if (subjectPattern.test(commit.subject)) {
            const bodyMatch = commit.body.match(bodyPattern);

            // check if the merge commit is a merge request
            if (bodyMatch) {
              const mergeRequest = bodyMatch[1];

              // fetch the merge request description
              const response = await fetchMergeRequest(mergeRequest, logger);

              const migrationSection = extractMigrationNotes(response);

              if (migrationNotes) {
                migrationNotes.push(migrationSection);
              }
            }
          }
        }

        // save migration notes to context
        if (migrationNotes.length > 0) {
          const joinedNotes = migrationNotes.join("\n\n");
          logger.log("Joining migration notes: ", joinedNotes);

          context.migrationNotes = joinedNotes;
          logger.log("Context 1:", context);
        }

        // return null to indicate no special release type
        return null;
      },
    },
    [
      "@semantic-release/gitlab",
      {
        successComment:
          "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:",
        labels: false,
        releasedLabels: false,
        assets: [{ path: "dist/*", label: "Distribution" }],
        publish: async (pluginConfig, context) => {
          const { nextRelease, logger } = context;
          const { migrationNotes } = context;

          logger.log("Context 2: ", context);

          if (migrationNotes) {
            logger.log("Appending migration notes to GitLab release notes...");
            nextRelease.notes += `\n\n### Migration Notes\n\n${migrationNotes}`;
          }

          // Call the default publish function
          const { publish } = require("@semantic-release/gitlab/lib/publish");
          return publish(pluginConfig, context);
        },
      },
    ],
  ],
};

// helper function to fetch merge request description from GitLab API
async function fetchMergeRequest(input, logger) {
  // extract the project and merge request number
  const [project, mergeRequestId] = input.split("!");
  const urlEncodedProject = encodeURIComponent(project);

  try {
    const response = await fetch(
      `${process.env.CI_API_V4_URL}/projects/${urlEncodedProject}/merge_requests/${mergeRequestId}`,
      {
        headers: {
          "PRIVATE-TOKEN": process.env.GITLAB_TOKEN,
        },
      }
    );
    const data = await response.json();
    return data;
  } catch (error) {
    logger.log("Error fetching merge request description: ", error);
    return null;
  }
}

// helper function to extract migration notes from the MR description
function extractMigrationNotes(mergeRequest) {
  const migrationNotesRegex = /## Migration Notes([\s\S]*?)(?=###|$)/;

  const match = mergeRequest.description.match(migrationNotesRegex);

  if (match) {
    return `Migration Notes ${mergeRequest.source_branch}` + match[1];
  }

  return null;
}

however, nothing is attached. it looks like my extension of the publish function is not executed

image

@JonasSchubert
Copy link
Contributor

HI @jnschbrt and sorry for the delayed response. IMO it is not possible to override a step of a plugin the way you intend to.
You try to override the default publish step of the gitlab plugin by providing it as a configuration option.
I am not that deep into the core code, but IMO it is not possible to override a step this way - at least I did not see anything in the docs.

I think you have to create your own plugin to handle this and update the migration notes there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants