Skip to content

feat: prevent re-runs of release workflow on merged pull requests #20

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

Merged
Merged
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
625 changes: 361 additions & 264 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions src/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { TerraformChangedModule, TerraformModule } from './terraform-module
* @param {Array<string>} commits - An array of commit messages to include in the changelog.
* @returns {string} A formatted changelog entry as a string.
*/
const createModuleChangelogEntry = (heading: string, commits: string[]): string => {
function createModuleChangelogEntry(heading: string, commits: string[]): string {
const currentDate = new Date().toISOString().split('T')[0]; // Format: YYYY-MM-DD
const changelogContent: string[] = [`## \`${heading}\` (${currentDate})\n`];

Expand All @@ -19,15 +19,15 @@ const createModuleChangelogEntry = (heading: string, commits: string[]): string
}

return changelogContent.join('\n');
};
}

/**
* Retrieves the global pull request changelog.
*
* @param {TerraformChangedModule[]} terraformChangedModules - An array of changed Terraform modules.
* @returns {string} The content of the global pull request changelog.
*/
export const getPullRequestChangelog = (terraformChangedModules: TerraformChangedModule[]): string => {
export function getPullRequestChangelog(terraformChangedModules: TerraformChangedModule[]): string {
const pullRequestChangelog: string[] = [];
const { prNumber, prTitle } = context;

Expand All @@ -47,15 +47,15 @@ export const getPullRequestChangelog = (terraformChangedModules: TerraformChange
}

return pullRequestChangelog.join('\n\n');
};
}

/**
* Retrieves the changelog for a specific Terraform module.
*
* @param {ChangedTerraformModule} changedTerraformModule - The Terraform module whose changelog is to be retrieved.
* @returns {string} The content of the module's changelog.
*/
export const getModuleChangelog = (terraformChangedModule: TerraformChangedModule): string => {
export function getModuleChangelog(terraformChangedModule: TerraformChangedModule): string {
const { prNumber, prTitle, repoUrl } = context;
const { nextTagVersion, commitMessages } = terraformChangedModule;

Expand All @@ -75,7 +75,7 @@ export const getModuleChangelog = (terraformChangedModule: TerraformChangedModul
];

return createModuleChangelogEntry(nextTagVersion, commitMessagesWithPR);
};
}

/**
* Generates a changelog for a given Terraform module by concatenating the body
Expand Down
4 changes: 2 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const getKeywords = (inputName: string): string[] => {
/**
* Lazy-initialized configuration object.
*/
const initializeConfig = (): Config => {
function initializeConfig(): Config {
if (configInstance) {
return configInstance;
}
Expand Down Expand Up @@ -100,6 +100,6 @@ const initializeConfig = (): Config => {
endGroup();

return configInstance;
};
}

export const config: Config = initializeConfig();
5 changes: 5 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
export const GITHUB_ACTIONS_BOT_NAME = 'GitHub Actions';
export const GITHUB_ACTIONS_BOT_EMAIL = '41898282+github-actions[bot]@users.noreply.github.com';

export const PR_SUMMARY_MARKER = '<!-- techpivot/terraform-module-releaser — pr-summary-marker -->';
export const PR_RELEASE_MARKER = '<!-- techpivot/terraform-module-releaser — release-marker -->';

export const ERROR_PERMISSIONS = 'Ensure that the GitHub Actions workflow has the correct permissions';
12 changes: 6 additions & 6 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ let contextInstance: Context | null = null;
* @returns {string} The value of the environment variable.
* @throws {Error} If the environment variable is missing or invalid.
*/
const getRequiredEnvironmentVar = (name: string): string => {
function getRequiredEnvironmentVar(name: string): string {
const value = process.env[name];
if (!value || typeof value !== 'string') {
const errorMessage = `The ${name} environment variable is missing or invalid. This variable should be automatically set by GitHub for each workflow run. If this variable is missing or not correctly set, it indicates a serious issue with the GitHub Actions environment, potentially affecting the execution of subsequent steps in the workflow. Please review the workflow setup or consult the documentation for proper configuration.`;
Expand All @@ -98,14 +98,14 @@ const getRequiredEnvironmentVar = (name: string): string => {
}

return value;
};
}

/**
* Additional type guard to check if an object is a valid PullRequestEvent. By definition, we know that
* because the GITHUB_EVENT_NAME is "pull_request" the payload will be a PullRequestEvent. However,
* this validates runtime data additionally.
*/
const isPullRequestEvent = (payload: unknown): payload is PullRequestEvent => {
function isPullRequestEvent(payload: unknown): payload is PullRequestEvent {
return (
typeof payload === 'object' &&
payload !== null &&
Expand All @@ -119,7 +119,7 @@ const isPullRequestEvent = (payload: unknown): payload is PullRequestEvent => {
typeof (payload as PullRequestEvent).repository === 'object' &&
typeof (payload as PullRequestEvent).repository.full_name === 'string'
);
};
}

/**
* Lazily initializes the context object that contains details about the pull request and repository.
Expand All @@ -131,7 +131,7 @@ const isPullRequestEvent = (payload: unknown): payload is PullRequestEvent => {
* @returns {Context} The context object containing GitHub client and pull request information.
* @throws {Error} If this workflow is not running in the context of a pull request.
*/
const initializeContext = (): Context => {
function initializeContext(): Context {
if (contextInstance) {
return contextInstance;
}
Expand Down Expand Up @@ -195,7 +195,7 @@ const initializeContext = (): Context => {
} finally {
endGroup();
}
};
}

/**
* The exported `context` object, lazily initialized on first access, provides information about the repository,
Expand Down
14 changes: 9 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { info, setFailed } from '@actions/core';
import { config } from './config';
import { context } from './context';
import { commentOnPullRequest, getPullRequestCommits } from './pull-request';
import { addPostReleaseComment, addReleasePlanComment, getPullRequestCommits, hasReleaseComment } from './pull-request';
import { createTaggedRelease, deleteLegacyReleases, getAllReleases } from './releases';
import { deleteLegacyTags, getAllTags } from './tags';
import { installTerraformDocs } from './terraform-docs';
Expand All @@ -15,7 +15,10 @@ import { WikiStatus } from './wiki';
*/
export async function run(): Promise<void> {
try {
// @todo early exit check
if (await hasReleaseComment()) {
info('Release comment found. Exiting.');
return;
}

// Fetch all commits along with associated files in this PR
const commits = await getPullRequestCommits();
Expand Down Expand Up @@ -55,7 +58,7 @@ export async function run(): Promise<void> {
failure = errorMessage;
error = err as Error;
} finally {
await commentOnPullRequest(terraformChangedModules, terraformModuleNamesToRemove, {
await addReleasePlanComment(terraformChangedModules, terraformModuleNamesToRemove, {
status: wikiStatus,
errorMessage: failure,
});
Expand All @@ -66,8 +69,9 @@ export async function run(): Promise<void> {
throw error;
}
} else {
// Create the tagged release
await createTaggedRelease(terraformChangedModules);
// Create the tagged release and post a comment to the PR
const updatedModules = await createTaggedRelease(terraformChangedModules);
await addPostReleaseComment(updatedModules);

// Delete legacy releases and tags (Ensure we delete releases first)
await deleteLegacyReleases(terraformModuleNamesToRemove, allReleases);
Expand Down
Loading