mirror of
https://github.com/ditkrg/todo-to-issue-action.git
synced 2026-01-22 13:56:44 +00:00
Merge pull request #270 from ditkrg/master
Support cross-repository issue creation
This commit is contained in:
commit
317efb4ff2
34
.github/workflows/example-cross-repo.yml
vendored
Normal file
34
.github/workflows/example-cross-repo.yml
vendored
Normal 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
|
||||
@ -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}'
|
||||
|
||||
63
README.md
63
README.md
@ -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 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!
|
||||
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!
|
||||
|
||||
[](https://ko-fi.com/alstr18858)
|
||||
|
||||
110
action.yml
110
action.yml
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user