Merge pull request #270 from ditkrg/master

Support cross-repository issue creation
This commit is contained in:
Alastair Mooney 2025-06-06 17:54:49 +01:00 committed by GitHub
commit 317efb4ff2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 179 additions and 36 deletions

View File

@ -0,0 +1,34 @@
name: Create TODO Issues in Another Repository
# NOTE: This is an example for when the TARGET_REPO feature is released.
# The current published version of the action does not yet have this feature.
on:
push:
branches: [main, master]
permissions:
contents: read
issues: write
jobs:
todo-to-issue:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Required to get the diff between commits
- name: TODO to Issue
# Use the local version of the action (after you've made the changes)
uses: ./
with:
TARGET_REPO: "my-org/target-repo" # Replace with your target repository
TOKEN: ${{ secrets.CROSS_REPO_TOKEN }} # Token with access to the target repository
CLOSE_ISSUES: "true" # Optional: close issues when TODOs are removed
AUTO_ASSIGN: "true" # Optional: assign issues to the committer
# Other optional configurations:
# IDENTIFIERS: '{"TODO": "TODO:", "FIXME": "Fix needed:"}' # Custom identifiers for TODOs
# LABELS: 'todo,fixme' # Default labels to apply to all created issues

View File

@ -17,13 +17,14 @@ class GitHubClient(Client):
self.base_url = f'{self.github_url}/'
self.repos_url = f'{self.base_url}repos/'
self.repo = os.getenv('INPUT_REPO')
self.target_repo = os.getenv('INPUT_TARGET_REPO', self.repo) # Default to current repo if not specified
self.before = os.getenv('INPUT_BEFORE')
self.sha = os.getenv('INPUT_SHA')
self.commits = json.loads(os.getenv('INPUT_COMMITS')) or []
self.__init_diff_url__()
self.token = os.getenv('INPUT_TOKEN')
self.issues_url = f'{self.repos_url}{self.repo}/issues'
self.milestones_url = f'{self.repos_url}{self.repo}/milestones'
self.issues_url = f'{self.repos_url}{self.target_repo}/issues'
self.milestones_url = f'{self.repos_url}{self.target_repo}/milestones'
self.issue_headers = {
'Content-Type': 'application/json',
'Authorization': f'token {self.token}',
@ -394,4 +395,5 @@ class GitHubClient(Client):
return pr_request.status_code
def get_issue_url(self, new_issue_number):
return f'{self.line_base_url}{self.repo}/issues/{new_issue_number}'
"""Get the URL for the issue."""
return f'{self.line_base_url}{self.target_repo}/issues/{new_issue_number}'

View File

@ -55,6 +55,65 @@ def hello_world():
print('Hello world!')
```
### Cross-Repository Issues
The action supports creating issues in a different repository than the one where the TODO comments are found. This requires:
1. Setting the `TARGET_REPO` input to specify the target repository (e.g., "owner/repo")
2. Providing appropriate authentication:
- For public repositories or when the target repository is in the same organization, use the default `GITHUB_TOKEN`:
```yaml
- uses: alstr/todo-to-issue-action@v5
with:
TARGET_REPO: "my-org/target-repo"
```
- For private repositories, provide GitHub App credentials:
```yaml
- uses: alstr/todo-to-issue-action@v5
with:
TARGET_REPO: "target-org/target-repo"
APP_ID: ${{ secrets.APP_ID }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
OWNER: "target-org"
```
The action will automatically:
1. Use the default `GITHUB_TOKEN` for same-repo or public repository access
2. Generate a GitHub App token when `APP_ID` and `PRIVATE_KEY` are provided for private repository access
### GitHub App Setup
To use the action with private repositories, you'll need to:
1. Create a GitHub App:
- Go to your GitHub account settings
- Navigate to "Developer settings" (bottom of the left sidebar)
- Click "GitHub Apps" and then "New GitHub App"
- Fill in the following details:
- **GitHub App name**: Choose a unique name (e.g., "TODO-to-Issue-App")
- **Homepage URL**: Your repository URL
- **Webhook**: Leave disabled
- **Repository permissions**:
- Issues: Read & Write
- Pull requests: Read & Write (if using PR integration)
- **Where can this GitHub App be installed?**: Any account
- Click "Create GitHub App"
- On the next page, click "Generate a private key" to download your private key file
- Note down the "App ID" shown on the page
2. Store the following secrets in your repository:
- Go to your repository's "Settings" → "Secrets and variables" → "Actions"
- Add two new repository secrets:
- `APP_ID`: The App ID you noted down
- `PRIVATE_KEY`: The entire contents of the private key file you downloaded (including the BEGIN and END lines)
3. Install the GitHub App:
- Go back to your GitHub App settings
- Click "Install App" in the left sidebar
- Choose the target repository where you want to create issues
- Click "Install"
As per the [Google Style Guide](https://google.github.io/styleguide/cppguide.html#TODO_Comments), you can provide a _reference_ after the TODO identifier:
```python
@ -289,7 +348,7 @@ using the `LANGUAGES` input.
Just create a file that contains an array of languages, each with the following properties:
| Property | Description |
|------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| language | The unique name of the language |
| extensions | A list of file extensions for the custom language |
| markers | A list of objects (see example below) to declare the comment markers. Make sure to escape all special Markdown characters with a double backslash. |
@ -535,6 +594,6 @@ Thanks to all those who have [contributed](https://github.com/alstr/todo-to-issu
## Supporting the Project
If youve found this action helpful and it has made your workflow easier, please consider buying a coffee to help keep it going. Thank you in advance!
If you've found this action helpful and it has made your workflow easier, please consider buying a coffee to help keep it going. Thank you in advance!
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/alstr18858)

View File

@ -1,88 +1,136 @@
name: 'TODO to Issue'
description: 'Converts IDE TODO comments to GitHub issues'
author: 'Alastair Mooney'
name: "TODO to Issue"
description: "Converts IDE TODO comments to GitHub issues"
author: "Alastair Mooney"
runs:
using: 'docker'
image: 'docker://ghcr.io/alstr/todo-to-issue-action:v5.1.12'
using: "composite"
steps:
- name: Generate token for private repository access
if: ${{ inputs.TARGET_REPO != '' && inputs.APP_ID != '' }}
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ inputs.APP_ID }}
private-key: ${{ inputs.PRIVATE_KEY }}
owner: ${{ inputs.OWNER }}
repositories: ${{ inputs.TARGET_REPO }}
shell: bash
- name: Run TODO to Issue action
uses: docker://ghcr.io/alstr/todo-to-issue-action:v5.1.12
with:
REPO: ${{ inputs.REPO }}
BEFORE: ${{ inputs.BEFORE }}
COMMITS: ${{ inputs.COMMITS }}
DIFF_URL: ${{ inputs.DIFF_URL }}
SHA: ${{ inputs.SHA }}
TOKEN: ${{ inputs.APP_ID != '' && steps.generate-token.outputs.token || inputs.TOKEN }}
TARGET_REPO: ${{ inputs.TARGET_REPO }}
CLOSE_ISSUES: ${{ inputs.CLOSE_ISSUES }}
AUTO_P: ${{ inputs.AUTO_P }}
PROJECT: ${{ inputs.PROJECT }}
PROJECTS_SECRET: ${{ inputs.PROJECTS_SECRET }}
IGNORE: ${{ inputs.IGNORE }}
AUTO_ASSIGN: ${{ inputs.AUTO_ASSIGN }}
ACTOR: ${{ inputs.ACTOR }}
ISSUE_TEMPLATE: ${{ inputs.ISSUE_TEMPLATE }}
IDENTIFIERS: ${{ inputs.IDENTIFIERS }}
GITHUB_URL: ${{ inputs.GITHUB_URL }}
GITHUB_SERVER_URL: ${{ inputs.GITHUB_SERVER_URL }}
ESCAPE: ${{ inputs.ESCAPE }}
LANGUAGES: ${{ inputs.LANGUAGES }}
NO_STANDARD: ${{ inputs.NO_STANDARD }}
INSERT_ISSUE_URLS: ${{ inputs.INSERT_ISSUE_URLS }}
branding:
icon: 'check-square'
color: 'orange'
icon: "check-square"
color: "orange"
inputs:
REPO:
description: "The path to the repository where the action will be used, e.g. 'alstr/my-repo' (automatically set)"
required: false
default: '${{ github.repository }}'
default: "${{ github.repository }}"
BEFORE:
description: 'The SHA of the last pushed commit (automatically set)'
description: "The SHA of the last pushed commit (automatically set)"
required: false
default: '${{ github.event.before || github.base_ref }}'
default: "${{ github.event.before || github.base_ref }}"
COMMITS:
description: 'An array of commit objects describing the pushed commits (automatically set)'
description: "An array of commit objects describing the pushed commits (automatically set)"
required: false
default: '${{ toJSON(github.event.commits) }}'
default: "${{ toJSON(github.event.commits) }}"
DIFF_URL:
description: 'The URL to use to get the diff (automatically set)'
description: "The URL to use to get the diff (automatically set)"
required: false
default: '${{ github.event.pull_request.diff_url }}'
default: "${{ github.event.pull_request.diff_url }}"
SHA:
description: 'The SHA of the latest commit (automatically set)'
description: "The SHA of the latest commit (automatically set)"
required: false
default: '${{ github.sha }}'
default: "${{ github.sha }}"
TOKEN:
description: 'The GitHub access token to allow us to retrieve, create and update issues (automatically set)'
description: "The GitHub access token to allow us to retrieve, create and update issues (automatically set)"
required: false
default: ${{ github.token }}
TARGET_REPO:
description: "Optional target repository to create issues in (e.g. 'owner/repo'). If not provided, issues will be created in the current repository."
required: false
APP_ID:
description: "GitHub App ID for generating tokens to access private repositories"
required: false
PRIVATE_KEY:
description: "Private key for the GitHub App (do not enter the actual secret)"
required: false
OWNER:
description: "Owner of the target repository (required if using GitHub App authentication)"
required: false
CLOSE_ISSUES:
description: 'Optional input specifying whether to attempt to close an issue when a TODO is removed'
description: "Optional input specifying whether to attempt to close an issue when a TODO is removed"
required: false
default: true
AUTO_P:
description: 'For multiline TODOs, format each line as a new paragraph when creating the issue'
description: "For multiline TODOs, format each line as a new paragraph when creating the issue"
required: false
default: true
PROJECT:
description: "User or organization project to link issues to, format 'project_type/owner/project_name'"
required: false
PROJECTS_SECRET:
description: 'Encrypted secret corresponding to your personal access token (do not enter the actual secret)'
description: "Encrypted secret corresponding to your personal access token (do not enter the actual secret)"
required: false
IGNORE:
description: 'A collection of comma-delimited regular expression that matches files that should be ignored when searching for TODOs'
description: "A collection of comma-delimited regular expression that matches files that should be ignored when searching for TODOs"
required: false
AUTO_ASSIGN:
description: 'Automatically assign new issues to the user who triggered the action'
description: "Automatically assign new issues to the user who triggered the action"
required: false
default: false
ACTOR:
description: 'The username of the person who triggered the action (automatically set)'
description: "The username of the person who triggered the action (automatically set)"
required: false
default: '${{ github.actor }}'
default: "${{ github.actor }}"
ISSUE_TEMPLATE:
description: 'The template used to format new issues'
description: "The template used to format new issues"
required: false
IDENTIFIERS:
description: 'Dictionary of custom identifiers'
description: "Dictionary of custom identifiers"
required: false
GITHUB_URL:
description: 'Base url of GitHub API'
description: "Base url of GitHub API"
required: false
default: ${{ github.api_url }}
GITHUB_SERVER_URL:
description: 'Base URL of GitHub web interface'
description: "Base URL of GitHub web interface"
required: false
default: ${{ github.server_url }}
ESCAPE:
description: 'Escape all special Markdown characters'
description: "Escape all special Markdown characters"
required: false
default: true
LANGUAGES:
description: 'A collection of comma-delimited URLs or local paths for custom language files'
description: "A collection of comma-delimited URLs or local paths for custom language files"
required: false
NO_STANDARD:
description: "Exclude loading the default 'syntax.json' and 'languages.yml' files from the repository"
required: false
default: false
INSERT_ISSUE_URLS:
description: 'Whether the action should insert the URL for a newly-created issue into the associated TODO comment'
description: "Whether the action should insert the URL for a newly-created issue into the associated TODO comment"
required: false
default: false