diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 9893d233e16f..000000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug, needs triage -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. Include the version(s) of DSpace where you've seen this problem. Link to examples if they are public. - -**To Reproduce** -Steps to reproduce the behavior: -1. Do this -2. Then this... - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Related work** -Link to any related tickets or PRs here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 34cc2c9e4f38..000000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest a new feature for this project -title: '' -labels: new feature, needs triage -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives or workarounds you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/actions/project-management-action/Dockerfile b/.github/actions/project-management-action/Dockerfile new file mode 100644 index 000000000000..1d3301259e4e --- /dev/null +++ b/.github/actions/project-management-action/Dockerfile @@ -0,0 +1,10 @@ +# Container image that runs your code +FROM alpine:3.10 + +RUN apk add --no-cache --no-progress curl jq + +# Copies your code file from your action repository to the filesystem path `/` of the container +COPY entrypoint.sh /entrypoint.sh +RUN chmod 777 /entrypoint.sh +# Code file to execute when the docker container starts up (`entrypoint.sh`) +ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/project-management-action/LICENSE b/.github/actions/project-management-action/LICENSE new file mode 100644 index 000000000000..c4f50f8a29e8 --- /dev/null +++ b/.github/actions/project-management-action/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Sergio Pintaldi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.github/actions/project-management-action/README.md b/.github/actions/project-management-action/README.md new file mode 100644 index 000000000000..1b2fa18c17e2 --- /dev/null +++ b/.github/actions/project-management-action/README.md @@ -0,0 +1,132 @@ +# GitHub Action for Assign to One Project + +[![Docker Cloud Automated build](https://img.shields.io/docker/cloud/automated/srggrs/assign-one-project-github-action)][docker] +[![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/srggrs/assign-one-project-github-action)][docker] +[![Docker Pulls](https://img.shields.io/docker/pulls/srggrs/assign-one-project-github-action)][docker] +[![GitHub license](https://img.shields.io/github/license/srggrs/assign-one-project-github-action.svg)][license] +![Latest Version](https://img.shields.io/github/v/release/srggrs/assign-one-project-github-action?color=orange&label=latest%20release) + +[docker]: https://hub.docker.com/r/srggrs/assign-one-project-github-action +[license]: https://github.com/srggrs/assign-one-project-github-action/blob/master/LICENSE + +Automatically add an issue or pull request to specific [GitHub Project](https://help.github.com/articles/about-project-boards/) when you __create__ and/or __label__ them. By default, the issues are assigned to the __`To do`__ column and the pull requests to the __`In progress`__ one, so make sure you have those columns in your project dashboard. But the workflow __allowed you to specify the column name as input__, so you can assign the issues/PRs based on a set of conditions to a specific column of a specific project. + +## Latest features: + +* included `issue_comment` as trigger for this action. +* added project pagination for searching 100+ GitHub projects. + +## Acknowledgment & Motivations + +This action has been modified from the original action from [masutaka](https://github.com/masutaka/github-actions-all-in-one-project). I needed to fix it as the original docker container would not build. Also I think the GitHub Action syntax changed a bit. + +I would like to thank @SunRunAway for adding the labelling functionality and custom column input. + +## Inputs + +### `project` + +**Required** The url of the project to be assigned to. + +### `column_name` + +The column name of the project, defaults to `'To do'` for issues and `'In progress'` for pull requests. + +## Example usage + +Examples of action: + +### Repository project + +```yaml +name: Auto Assign to Project(s) + +on: + issues: + types: [opened, labeled] + pull_request: + types: [opened, labeled] + issue_comment: + types: [created] +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + assign_one_project: + runs-on: ubuntu-latest + name: Assign to One Project + steps: + - name: Assign NEW issues and NEW pull requests to project 2 + uses: srggrs/assign-one-project-github-action@1.2.1 + if: github.event.action == 'opened' + with: + project: 'https://github.com/srggrs/assign-one-project-github-action/projects/2' + + - name: Assign issues and pull requests with `bug` label to project 3 + uses: srggrs/assign-one-project-github-action@1.2.1 + if: | + contains(github.event.issue.labels.*.name, 'bug') || + contains(github.event.pull_request.labels.*.name, 'bug') + with: + project: 'https://github.com/srggrs/assign-one-project-github-action/projects/3' + column_name: 'Labeled' +``` + +#### __Notes__ +Be careful of using the conditions above (opened and labeled issues/PRs) because in such workflow, if the issue/PR is opened and labeled at the same time, it will be assigned to __both__ projects! + + +You can use any combination of conditions. For example, to assign new issues or issues labeled with 'mylabel' to a project column, use: +```yaml +... + +if: | + github.event_name == 'issues' && + ( + github.event.action == 'opened' || + contains(github.event.issue.labels.*.name, 'mylabel') + ) +... +``` + +### Organisation or User project + +Generate a token from the Organisation settings or User Settings and add it as a secret in the repository secrets as `MY_GITHUB_TOKEN` + +```yaml +name: Auto Assign to Project(s) + +on: + issues: + types: [opened, labeled] + pull_request_target: + types: [opened, labeled] + issue_comment: + types: [created] +env: + MY_GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} + +jobs: + assign_one_project: + runs-on: ubuntu-latest + name: Assign to One Project + steps: + - name: Assign NEW issues and NEW pull requests to project 2 + uses: srggrs/assign-one-project-github-action@1.2.1 + if: github.event.action == 'opened' + with: + project: 'https://github.com/srggrs/assign-one-project-github-action/projects/2' + + - name: Assign issues and pull requests with `bug` label to project 3 + uses: srggrs/assign-one-project-github-action@1.2.1 + if: | + contains(github.event.issue.labels.*.name, 'bug') || + contains(github.event.pull_request.labels.*.name, 'bug') + with: + project: 'https://github.com/srggrs/assign-one-project-github-action/projects/3' + column_name: 'Labeled' +``` + +## [Change Log](./CHANGELOG.md) + +Please refer to the list of changes [here](./CHANGELOG.md) diff --git a/.github/actions/project-management-action/action.yml b/.github/actions/project-management-action/action.yml new file mode 100644 index 000000000000..40f7a1208834 --- /dev/null +++ b/.github/actions/project-management-action/action.yml @@ -0,0 +1,22 @@ +# action.yml +name: 'Assign to One Project' +description: 'Assign new/labeled Issue or Pull Request to a specific project dashboard column' +author: srggrs +inputs: + project: + description: 'The url of the project to be assigned to.' + required: true + column_name: + description: 'The column name of the project, defaults to "To do" for issues and "In progress" for pull requests.' + required: false + +runs: + using: 'docker' + image: 'Dockerfile' + args: + - ${{ inputs.project }} + - ${{ inputs.column_name }} + +branding: + icon: 'box' + color: 'red' diff --git a/.github/actions/project-management-action/entrypoint.sh b/.github/actions/project-management-action/entrypoint.sh new file mode 100644 index 000000000000..05b81c7d2d0c --- /dev/null +++ b/.github/actions/project-management-action/entrypoint.sh @@ -0,0 +1,150 @@ +#!/bin/sh -l + +PROJECT_URL="$INPUT_PROJECT" +if [ -z "$PROJECT_URL" ]; then + echo "Project input variable is not defined." >&2 + exit 1 +fi + +get_project_type() { + _PROJECT_URL="$1" + + case "$_PROJECT_URL" in + https://github.com/orgs/*) + echo "org" + ;; + https://github.com/users/*) + echo "user" + ;; + https://github.com/*/projects/*) + echo "repo" + ;; + *) + echo "Invalid Project URL: '$_PROJECT_URL' . Please pass a valid Project URL in the project input variable" >&2 + exit 1 + ;; + esac + + unset _PROJECT_URL +} + +get_next_url_from_headers() { + _HEADERS_FILE=$1 + grep -i '^link' "$_HEADERS_FILE" | tr ',' '\n'| grep \"next\" | sed 's/.*<\(.*\)>.*/\1/' +} + +find_project_id() { + _PROJECT_TYPE="$1" + _PROJECT_URL="$2" + + case "$_PROJECT_TYPE" in + org) + _ORG_NAME=$(echo "$_PROJECT_URL" | sed -e 's@https://github.com/orgs/\([^/]\+\)/projects/[0-9]\+@\1@') + _ENDPOINT="https://api.github.com/orgs/$_ORG_NAME/projects?per_page=100" + ;; + user) + _USER_NAME=$(echo "$_PROJECT_URL" | sed -e 's@https://github.com/users/\([^/]\+\)/projects/[0-9]\+@\1@') + _ENDPOINT="https://api.github.com/users/$_USER_NAME/projects?per_page=100" + ;; + repo) + _ENDPOINT="https://api.github.com/repos/$GITHUB_REPOSITORY/projects?per_page=100" + ;; + esac + + _NEXT_URL="$_ENDPOINT" + + while : ; do + + _PROJECTS=$(curl -s -X GET -u "$GITHUB_ACTOR:$TOKEN" --retry 3 \ + -H 'Accept: application/vnd.github.inertia-preview+json' \ + -D /tmp/headers \ + "$_NEXT_URL") + + _PROJECTID=$(echo "$_PROJECTS" | jq -r ".[] | select(.html_url == \"$_PROJECT_URL\").id") + _NEXT_URL=$(get_next_url_from_headers '/tmp/headers') + + if [ "$_PROJECTID" != "" ]; then + echo "$_PROJECTID" + elif [ "$_NEXT_URL" == "" ]; then + echo "No project was found." >&2 + exit 1 + fi + done + + unset _PROJECT_TYPE _PROJECT_URL _ORG_NAME _USER_NAME _ENDPOINT _PROJECTS _PROJECTID _NEXT_URL +} + +find_column_id() { + _PROJECT_ID="$1" + _INITIAL_COLUMN_NAME="$2" + + _COLUMNS=$(curl -s -X GET -u "$GITHUB_ACTOR:$TOKEN" --retry 3 \ + -H 'Accept: application/vnd.github.inertia-preview+json' \ + "https://api.github.com/projects/$_PROJECT_ID/columns") + + + echo "$_COLUMNS" | jq -r ".[] | select(.name == \"$_INITIAL_COLUMN_NAME\").id" + unset _PROJECT_ID _INITIAL_COLUMN_NAME _COLUMNS +} + +PROJECT_TYPE=$(get_project_type "${PROJECT_URL:? required this environment variable}") + +if [ "$PROJECT_TYPE" = org ] || [ "$PROJECT_TYPE" = user ]; then + if [ -z "$MY_GITHUB_TOKEN" ]; then + echo "MY_GITHUB_TOKEN not defined" >&2 + exit 1 + fi + + TOKEN="$MY_GITHUB_TOKEN" # It's User's personal access token. It should be secret. +else + if [ -z "$GITHUB_TOKEN" ]; then + echo "GITHUB_TOKEN not defined" >&2 + exit 1 + fi + + TOKEN="$GITHUB_TOKEN" # GitHub sets. The scope in only the repository containing the workflow file. +fi + +INITIAL_COLUMN_NAME="$INPUT_COLUMN_NAME" +if [ -z "$INITIAL_COLUMN_NAME" ]; then + # assing the column name by default + INITIAL_COLUMN_NAME='To do' + if [ "$GITHUB_EVENT_NAME" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "pull_request_target" ]; then + echo "changing column name for PR event" + INITIAL_COLUMN_NAME='In progress' + fi +fi + + +PROJECT_ID=$(find_project_id "$PROJECT_TYPE" "$PROJECT_URL") +INITIAL_COLUMN_ID=$(find_column_id "$PROJECT_ID" "${INITIAL_COLUMN_NAME:? required this environment variable}") + +if [ -z "$INITIAL_COLUMN_ID" ]; then + echo "Column name '$INITIAL_COLUMN_ID' is not found." >&2 + exit 1 +fi + +case "$GITHUB_EVENT_NAME" in + issues|issue_comment) + ISSUE_ID=$(jq -r '.issue.id' < "$GITHUB_EVENT_PATH") + + # Add this issue to the project column + curl -s -X POST -u "$GITHUB_ACTOR:$TOKEN" --retry 3 \ + -H 'Accept: application/vnd.github.inertia-preview+json' \ + -d "{\"content_type\": \"Issue\", \"content_id\": $ISSUE_ID}" \ + "https://api.github.com/projects/columns/$INITIAL_COLUMN_ID/cards" + ;; + pull_request|pull_request_target) + PULL_REQUEST_ID=$(jq -r '.pull_request.id' < "$GITHUB_EVENT_PATH") + + # Add this pull_request to the project column + curl -s -X POST -u "$GITHUB_ACTOR:$TOKEN" --retry 3 \ + -H 'Accept: application/vnd.github.inertia-preview+json' \ + -d "{\"content_type\": \"PullRequest\", \"content_id\": $PULL_REQUEST_ID}" \ + "https://api.github.com/projects/columns/$INITIAL_COLUMN_ID/cards" + ;; + *) + echo "Nothing to be done on this action: '$GITHUB_EVENT_NAME'" >&2 + exit 1 + ;; +esac diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 651f9e167544..f36efc7b9733 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,11 +1,11 @@ -| Phases | MM | MB | Total | -|-----------------|----:|----:|-------:| -| ETA | 0 | 0 | 0 | -| Developing | 0 | 0 | 0 | -| Review | 0 | 0 | 0 | -| Total | - | - | 0 | -| ETA est. | | | 0 | -| ETA cust. | - | - | 0 | +| Phases | MM | MB | MR | JM | Total | +|-----------------|----:|----:|-----:|-----:|-------:| +| ETA | 0 | 0 | 0 | 0 | 0 | +| Developing | 0 | 0 | 0 | 0 | 0 | +| Review | 0 | 0 | 0 | 0 | 0 | +| Total | - | - | - | - | 0 | +| ETA est. | | | | | 0 | +| ETA cust. | - | - | - | - | 0 | ## Problem description ### Reported issues ### Not-reported issues @@ -13,13 +13,3 @@ (Write here, if there is needed describe some specific problem. Erase it, when it is not needed.) ## Problems (Write here, if some unexpected problems occur during solving issues. Erase it, when it is not needed.) - -## Checklist -_This checklist provides a reminder of what we are going to look for when reviewing your PR. You need not complete this checklist prior to creating your PR (draft PRs are always welcome). If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!_ - -- [ ] My PR is small in size (e.g. less than 1,000 lines of code, not including comments & integration tests). Exceptions may be made if previously agreed upon. -- [ ] My PR passes Checkstyle validation based on the [Code Style Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Style+Guide). -- [ ] My PR includes Javadoc for _all new (or modified) public methods and classes_. It also includes Javadoc for large or complex private methods. -- [ ] My PR passes all tests and includes new/updated Unit or Integration Tests based on the [Code Testing Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Testing+Guide). -- [ ] If my PR includes new, third-party dependencies (in any `pom.xml`), I've made sure their licenses align with the [DSpace BSD License](https://github.com/DSpace/DSpace/blob/main/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation. -- [ ] If my PR modifies the REST API, I've linked to the REST Contract page (or open PR) related to this change. diff --git a/.github/workflows/new_issue_assign.yml b/.github/workflows/new_issue_assign.yml new file mode 100644 index 000000000000..f958615fbf63 --- /dev/null +++ b/.github/workflows/new_issue_assign.yml @@ -0,0 +1,20 @@ +name: New issue assign +on: + issues: + types: [opened] + +env: + MY_GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} + +jobs: + assign_one_project: + runs-on: ubuntu-latest + name: Assign to One Project + steps: + - uses: actions/checkout@v3 + - name: Assign NEW issues to dspace project + uses: ./.github/actions/project-management-action + if: github.event.action == 'opened' + with: + project: 'https://github.com/orgs/dataquest-dev/projects/6' + column_name: 'To do'