UNPKG

@shopware-ag/gh-project-automation

Version:
484 lines (466 loc) 20.7 kB
import { GitHub } from '@actions/github/lib/utils.js'; import { Context } from '@actions/github/lib/context.js'; import * as core from '@actions/core'; import * as exec from '@actions/exec'; import * as glob from '@actions/glob'; import * as io from '@actions/io'; import fetch from 'node-fetch'; import { User } from '@slack/web-api/dist/types/response/UsersLookupByEmailResponse'; type GitHubIssue = { id: string; title: string; number?: number; url?: string; status?: string; labels: Label[]; type?: string; owner?: string; repository?: string; assignees?: { login: string; }; reviewRequests?: { login: string; }; }; type GitHubComment = { id: string; author: { login: string; }; body: string; url?: string; }; type Label = { id: string; name: string; url: string; description?: string; color: string; }; type Labelable = { id: string; number: number; title: string; labels: { nodes: [ { name: string; } ]; }; }; type GitHubMilestone = { id: number; url: string; html_url: string; labels_url: string; node_id: string; number: number; state: "open" | "closed"; title: string; description: string | null; created_at: string; updated_at: string; closed_at: string | null; due_on: string | null; open_issues: number; closed_issues: number; }; type JiraIssue = { id: string; title: string; key: string; url?: string; status?: string; labels: string[]; type?: string; }; type QueryResponse = { repository: { issues?: { pageInfo: { hasNextPage: boolean; endCursor: string; }; nodes: [ { id: string; number: number; title: string; labels: { nodes: [ { name: string; } ]; }; } ]; }; pullRequests?: { pageInfo: { hasNextPage: boolean; endCursor: string; }; nodes: [ { id: string; number: number; title: string; labels: { nodes: [ { name: string; } ]; }; } ]; }; }; }; type Toolkit = { github: InstanceType<typeof GitHub>; context: Context; core: typeof core; exec: typeof exec; glob: typeof glob; io: typeof io; fetch: typeof fetch; }; declare function closeIssue(toolkit: Toolkit, issueId: string, reason?: string): Promise<void>; declare function closePullRequest(toolkit: Toolkit, pullRequestId: string): Promise<void>; declare function getLabelByName(toolkit: Toolkit, repository: string, labelName: string): Promise<any>; declare function addLabelToLabelable(toolkit: Toolkit, labelId: string, labelableId: string): Promise<void>; declare function findIssueWithProjectItems(toolkit: Toolkit, number: number): Promise<{ node_id: any; number: any; projectItems: any; }>; declare function findPRWithProjectItems(toolkit: Toolkit, number: number): Promise<{ node_id: any; number: any; projectItems: any; }>; declare function setFieldValue(toolkit: Toolkit, data: { projectId: string; itemId: string; fieldId: string; valueId: string; }): Promise<any>; declare function getProjectInfo(toolkit: Toolkit, data: { number: number; organization?: string; }): Promise<{ node_id: any; title: any; fields: any; }>; declare function addProjectItem(toolkit: Toolkit, data: { projectId: string; issueId: string; }): Promise<{ node_id: any; }>; /** * getProjectIdByNumber fetches the project ID for a given project number. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param number - The project number to get the ID for. * @param organization - The organization name whose projects to consider. */ declare function getProjectIdByNumber(toolkit: Toolkit, number: number, organization?: string | null): Promise<any>; /** * getIssuesByProject fetches all issues from a project. * * @remarks * This function uses pagination to fetch all issues from a project. * It will keep fetching until all issues are retrieved. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param projectId - The ID of the project to fetch issues from. * @param cursor - The cursor for pagination. * @param carry - The issues already fetched. */ declare function getIssuesByProject(toolkit: Toolkit, projectId: string, cursor?: string | null, carry?: GitHubIssue[] | null): Promise<GitHubIssue[]>; /** * getCommentsForIssue fetches all comments for a given issue. * * @remarks * This function uses pagination to fetch all comments for an issue. * It will keep fetching until all comments are retrieved. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param issueId - The ID of the issue to fetch comments for. * @param cursor - The cursor for pagination. * @param carry - The comments already fetched. */ declare function getCommentsForIssue(toolkit: Toolkit, issueId: string, cursor?: string | null, carry?: GitHubComment[] | null): Promise<any[]>; /** * Gets pull requests matching the given search criteria * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param searchQuery - The GitHub search query to use */ declare function getPullRequests(toolkit: Toolkit, searchQuery: string): Promise<any>; declare function addComment(toolkit: Toolkit, issueId: string, commentBody: string): Promise<GitHubComment>; /** * getVerifiedDomainEmails fetches the verified domain emails for a user account associated with an enterprise. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param login - The login of the user. * @param organization - The organization name whose verified domains to consider. */ declare function getVerifiedDomainEmails(toolkit: Toolkit, login: string, organization: string): Promise<string[]>; /** * getMilestoneByTitle fetches a milestone by it's title. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param repo - The name of the repository * @param milestoneTitle the title of the milestone * @param organization - The organization name of the repository */ declare function getMilestoneByTitle(toolkit: Toolkit, repo: string, milestoneTitle: string, organization?: string): Promise<GitHubMilestone | undefined>; declare const jiraHost = "shopware.atlassian.net"; declare const jiraBaseUrl = "https://shopware.atlassian.net/rest/api/3"; /** * Makes an API call to JIRA with the provided endpoint and request body. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param endpoint - The JIRA API endpoint to call. * @param requestBody - The request body to send with the API call. * * @return The response from the JIRA API. */ declare function callJiraApi(toolkit: Toolkit, endpoint: string, requestBody: object): Promise<any>; declare class SlackClient { private webClient; constructor(token: string); getUserByEmail(toolkit: Toolkit, email: string): Promise<User | null>; sendIMToUser(userId: string, message: string): Promise<void>; } declare function cancelStuckWorkflows(toolkit: Toolkit, repo: string, organization?: string): Promise<void>; declare function checkMissingLiceneInRepos(toolkit: Toolkit, organization?: string): Promise<void>; /** * Branches that must never be deleted by {@link cleanupBranches}. Matches * long-lived release branches such as `6.5`, `6.5.0`, `6.6.x` and SaaS release * branches like `saas/2025/12`. * * This is the single source of truth for the exclude pattern used by the * branch-cleanup workflow; it is exported so it can be unit-tested and imported * by the workflow instead of being duplicated as a YAML string literal. */ declare const protectedReleaseBranchRegex: RegExp; declare function getOldBranches(toolkit: Toolkit, repo: string, excludeRegex?: string | RegExp, organization?: string): Promise<string[] | null>; declare function cleanupBranches(toolkit: Toolkit, repo: string, organization?: string, excludeRegex?: string | RegExp): Promise<void>; declare const docIssueReference: string; /** * getDevelopmentIssueForPullRequest fetches the development issue linked to a pull request. * * @remarks * This function searches for pull requests in the Shopware organization that match the given head and assignee. * It retrieves the first closing issue reference from the matching pull requests. * If a matching development issue is found, it returns the issue details; otherwise, it returns null. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param repo - The repository to search in, formatted as "owner/repo". * @param pullRequestNumber - The number of the pull request to search for. * @param pullRequestHead - The head branch of the pull request. * @param pullRequestAssignee - The assignee of the pull request. */ declare function getDevelopmentIssueForPullRequest(toolkit: Toolkit, repo: string, pullRequestNumber: number, pullRequestHead: string, pullRequestAssignee: string): Promise<GitHubIssue | null>; /** * getEpicsInProgressByProject fetches all epics in progress from a project. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param projectId - The ID of the project to fetch issues from. */ declare function getEpicsInProgressByProject(toolkit: Toolkit, projectId: string): Promise<GitHubIssue[]>; /** * createDocIssueComment creates a comment on a GitHub issue that references a documentation issue. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param issueId - The ID of the issue to comment on. * @param docIssueKey - The key of the documentation issue to reference. * @param content - The comment to add. */ declare function createDocIssueComment(toolkit: Toolkit, issueId: string, docIssueKey: string, content?: string | null): Promise<GitHubComment>; /** * hasDocIssueComment checks if a GitHub issue has a comment that references a documentation issue. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param issueId - The ID of the issue to check. */ declare function hasDocIssueComment(toolkit: Toolkit, issueId: string): Promise<boolean>; /** * referencesDocIssue checks if a comment contains a link to a documentation issue. * * @param comment - The comment to check. */ declare function referencesDocIssue(comment: GitHubComment): boolean; /** * Cleans up needs-triage in issues and pull requests * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param dryRun - If true, only log what would be done without making changes. * * @remarks * This function finds all open issues and pull requests and ensures they have either: * - The needs-triage label, or * - A label starting with 'domain/' or 'service/' * - If an item has a `domain/` or `service/` label, remove the `needs-triage` label * * Closed items are ignored. The function handles pagination to process all items. */ declare function cleanupNeedsTriage(toolkit: Toolkit, dryRun?: boolean): Promise<void>; declare function findWithProjectItems(toolkit: Toolkit): Promise<{ node_id: any; number: any; projectItems: any; }>; declare function linkClosingPR(toolkit: Toolkit, issueNumber: number, prReadToken: string, visibilityFilter?: string, org?: string, repo?: string): Promise<void>; /** * createDocumentationTask creates a documentation task in JIRA for a given GitHub issue. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param issue - The issue to create a documentation task for. * @param documentationProjectId - The ID of the documentation project. * @param description - The description of the documentation task. */ declare function createDocumentationTask(toolkit: Toolkit, issue: GitHubIssue, documentationProjectId?: number | null, description?: string | null): Promise<JiraIssue>; /** * setMilestoneForPR sets the milestone for a Pull request or an Issue. * If a milestone doesn't exists it will create one. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js */ declare function setMilestoneForPR(toolkit: Toolkit): Promise<void>; type MoveMilestoneLabelsOptions = { /** Current version whose milestone label should be moved, e.g. "6.7.10.0". */ version: string; /** Repository owner. Defaults to "shopware". */ owner?: string; /** Repository name. Defaults to "shopware". */ repo?: string; /** * When set, only PRs targeting this base branch are relabelled. PRs * targeting a release branch follow a different milestone scheme and must * not be bumped, so callers relabelling trunk PRs should pass "trunk". * When omitted, PRs targeting any base branch are relabelled. */ baseRefName?: string; /** Overrides the DRY_RUN env detection when provided. */ dryRun?: boolean; }; /** * moveMilestoneLabelsToNextVersion moves the `milestone/<version>` label to the * next patch version (`milestone/<version+1>`) on every open PR that still * carries it. It is used both when a release is tagged and when a release * branch is split off, so the operation is fully parameterized. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param options - see {@link MoveMilestoneLabelsOptions} */ declare function moveMilestoneLabelsToNextVersion(toolkit: Toolkit, options: MoveMilestoneLabelsOptions): Promise<void>; /** * updateMilestonesOnRelease updates the milestones on release if a PR didn't * get merged in the merge window. It reads the released version from the `TAG` * environment variable (e.g. "v6.7.10.0") and delegates to * {@link moveMilestoneLabelsToNextVersion} for shopware/shopware. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js */ declare function updateMilestonesOnRelease(toolkit: Toolkit): Promise<1 | undefined>; /** * Sets the status of issues in projects using the provided toolkit. * * @param toolkit - The toolkit instance to interact with the project management system. * @param props - The properties for setting the status. * @param props.toStatus - The status to set the issues to. * @param props.fromStatus - (Optional) The status to filter issues by before setting the new status. Can be a string which has to match exactly or an instance of RegExp * * @remarks * This function finds issues in projects and updates their status based on the provided `toStatus`. * If `fromStatus` is provided, only issues with the matching status will be updated. * If the `toStatus` option is not found in the project's status options, the issue will be skipped. * * @example * ```typescript * await setStatusInProjects({ github, context, core, exec, glob, io, fetch }, { toStatus: 'In Progress', fromStatus: 'Done' }); * ``` */ declare function setStatusInProjects(toolkit: Toolkit, props: { toStatus: string; fromStatus?: string | RegExp; }): Promise<void>; declare function syncPriorities(toolkit: Toolkit, excludeList?: number[]): Promise<void>; /** * createDocumentationTasksForProjects creates documentation tasks for all projects with the given project numbers. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param projectNumbers - The project numbers to create documentation tasks for. * @param organization - The organization name whose projects to consider. * @param documentationProjectId - The ID of the documentation project. * @param description - Prefix for the description of the documentation task. * @param comment - Prefix for the documentation task reference comment. */ declare function createDocumentationTasksForProjects(toolkit: Toolkit, projectNumbers: number[], organization?: string | null, documentationProjectId?: number | null, description?: string | null, comment?: string | null): Promise<void>; declare function markStaleIssues(toolkit: Toolkit, projectNumber: number, dryRun: boolean): Promise<void>; declare function closeStaleIssues(toolkit: Toolkit, dryRun: boolean): Promise<void>; /** * manageOldPullRequests checks for old pull requests and closes them if they have been inactive for a specified number of days. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param organization - The GitHub organization to check for old pull requests. * @param days - Consider pull requests old after this many days of inactivity. * @param close - If true, the pull request will be closed after sending the reminder. */ declare function manageOldPullRequests(toolkit: Toolkit, organization?: string, days?: number, close?: boolean, excludedRepositories?: string[]): Promise<void>; /** * Computed dates for the "branch-off and minor release" announcement, derived * from the first Monday of the month following `now`. */ type ReleaseSchedule = { /** The effective "today" (the override if given, otherwise `now`), as `YYYY-MM-DD`. */ today: string; /** The day the announcement should be sent, as `YYYY-MM-DD`. */ announcementDate: string; /** Human-readable on-prem release date, e.g. `Monday, July 7, 2025`. */ onpremReleaseDate: string; /** Human-readable branch-off date, e.g. `Monday, June 23, 2025`. */ branchoffDate: string; /** Whether `today` is the announcement day. */ notify: boolean; }; /** * Computes the release-announcement schedule. * * The on-prem release happens on the first Monday of the month after `now`. * Branch-off is 14 days before that, and the announcement 5 days before * branch-off. All calculations are performed in UTC to match the GitHub Actions * runner behaviour of the previous shell implementation. * * @param now - The current date. Only its year/month drive the schedule. * @param overrideToday - Optional `YYYY-MM-DD` string used in place of `now` * for the `notify` comparison (used for manual testing of the workflow). */ declare function computeReleaseSchedule(now: Date, overrideToday?: string | null): ReleaseSchedule; /** * Sends a message to a Slack user identified by their email address. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param emails - The email address(es) of the Slack user to send the message to. * @param message - The message to send. */ declare function sendSlackMessageForEMail(toolkit: Toolkit, emails: string[], message: string): Promise<void>; /** * Gets a Slack user by their email address. * * @param toolkit - Octokit instance. See: https://octokit.github.io/rest.js * @param emails - The email address(es) of the Slack user. * @param message - The message to send. */ declare function getSlackUserByEmail(toolkit: Toolkit, emails: string[]): Promise<User | null>; export { SlackClient, addComment, addLabelToLabelable, addProjectItem, callJiraApi, cancelStuckWorkflows, checkMissingLiceneInRepos, cleanupBranches, cleanupNeedsTriage, closeIssue, closePullRequest, closeStaleIssues, computeReleaseSchedule, createDocIssueComment, createDocumentationTask, createDocumentationTasksForProjects, docIssueReference, findIssueWithProjectItems, findPRWithProjectItems, findWithProjectItems, getCommentsForIssue, getDevelopmentIssueForPullRequest, getEpicsInProgressByProject, getIssuesByProject, getLabelByName, getMilestoneByTitle, getOldBranches, getProjectIdByNumber, getProjectInfo, getPullRequests, getSlackUserByEmail, getVerifiedDomainEmails, hasDocIssueComment, jiraBaseUrl, jiraHost, linkClosingPR, manageOldPullRequests, markStaleIssues, moveMilestoneLabelsToNextVersion, protectedReleaseBranchRegex, referencesDocIssue, sendSlackMessageForEMail, setFieldValue, setMilestoneForPR, setStatusInProjects, syncPriorities, updateMilestonesOnRelease }; export type { GitHubComment, GitHubIssue, GitHubMilestone, JiraIssue, Label, Labelable, MoveMilestoneLabelsOptions, QueryResponse, ReleaseSchedule, Toolkit };