diff --git a/.github/workflows/labeler-build-predictor.yml b/.github/workflows/labeler-build-predictor.yml deleted file mode 100644 index 1ffb01a79f0e..000000000000 --- a/.github/workflows/labeler-build-predictor.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: "Labeler: Build Predictor App" - -on: - # Allow dispatching the workflow via the Actions UI - workflow_dispatch: - inputs: - rebuild: - description: "Force a rebuild of the app" - type: boolean - -jobs: - build-predictor: - permissions: - actions: write - uses: dotnet/issue-labeler/.github/workflows/build-predictor.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 - with: - rebuild: ${{ inputs.rebuild }} \ No newline at end of file diff --git a/.github/workflows/labeler-cache-retention.yml b/.github/workflows/labeler-cache-retention.yml index 59210c5eed7a..5cdacfa05670 100644 --- a/.github/workflows/labeler-cache-retention.yml +++ b/.github/workflows/labeler-cache-retention.yml @@ -1,13 +1,40 @@ +# Workflow template imported and updated from: +# https://github.com/dotnet/issue-labeler/wiki/Onboarding +# +# See labeler.md for more information +# +# Regularly restore the prediction models from cache to prevent cache eviction name: "Labeler: Cache Retention" +# For more information about GitHub's action cache limits and eviction policy, see: +# https://docs.github.com/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy + on: schedule: - cron: "39 3 * * *" # 3:39 every day (arbitrary time daily, modified to different values in each repository) workflow_dispatch: + inputs: + cache_key: + description: "The cache key suffix to use for restoring the model from cache. Defaults to 'ACTIVE'." + required: true + default: "ACTIVE" + +env: + CACHE_KEY: ${{ inputs.cache_key || 'ACTIVE' }} jobs: - cache-retention: - # Do not run the workflow on forks outside the 'dotnet' org - if: ${{ github.repository_owner == 'dotnet' }} - uses: dotnet/issue-labeler/.github/workflows/cache-retention.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 \ No newline at end of file + restore-cache: + # Do not automatically run the workflow on forks outside the 'dotnet' org + if: ${{ github.event_name == 'workflow_dispatch' || github.repository_owner == 'dotnet' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + type: ["issues", "pulls"] + steps: + - uses: dotnet/issue-labeler/restore@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: ${{ matrix.type }} + cache_key: ${{ env.CACHE_KEY }} + fail-on-cache-miss: true diff --git a/.github/workflows/labeler-predict-issues.yml b/.github/workflows/labeler-predict-issues.yml index bb17c0aa7e07..88c36b9cab33 100644 --- a/.github/workflows/labeler-predict-issues.yml +++ b/.github/workflows/labeler-predict-issues.yml @@ -1,31 +1,58 @@ -name: "Labeler: Predict Issue Labels" +# Workflow template imported and updated from: +# https://github.com/dotnet/issue-labeler/wiki/Onboarding +# +# See labeler.md for more information +# +# Predict labels for Issues using a trained model +name: "Labeler: Predict (Issues)" on: - # Only automatically predict area labels when issues are originally opened + # Only automatically predict area labels when issues are first opened issues: types: opened # Allow dispatching the workflow via the Actions UI, specifying ranges of numbers workflow_dispatch: inputs: - issue_numbers: - description: "Issue Numbers (comma-separated list of ranges)" - type: string - model_cache_key: - description: "The cache key suffix to use for loading the model" - type: string + issues: + description: "Issue Numbers (comma-separated list of ranges)." required: true - default: "LIVE" + cache_key: + description: "The cache key suffix to use for restoring the model. Defaults to 'ACTIVE'." + required: true + default: "ACTIVE" + +env: + # Do not allow failure for jobs triggered automatically (as this causes red noise on the workflows list) + ALLOW_FAILURE: ${{ github.event_name == 'workflow_dispatch' }} + + LABEL_PREFIX: "Area-" + THRESHOLD: 0.40 jobs: - predict-issues: - # Do not run the workflow on forks outside the 'dotnet' org - if: ${{ github.repository_owner == 'dotnet' && (inputs.issue_numbers || github.event.issue.number) }} + predict-issue-label: + # Do not automatically run the workflow on forks outside the 'dotnet' org + if: ${{ github.event_name == 'workflow_dispatch' || github.repository_owner == 'dotnet' }} + runs-on: ubuntu-latest permissions: issues: write - uses: dotnet/issue-labeler/.github/workflows/predict-issues.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 - with: - model_cache_key: ${{ inputs.model_cache_key }} - issue_numbers: ${{ inputs.issue_numbers || github.event.issue.number }} - label_prefix: "Area-" - threshold: 0.40 + steps: + - name: "Restore issues model from cache" + id: restore-model + uses: dotnet/issue-labeler/restore@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: issues + fail-on-cache-miss: ${{ env.ALLOW_FAILURE }} + quiet: true + + - name: "Predict issue labels" + id: prediction + if: ${{ steps.restore-model.outputs.cache-hit == 'true' }} + uses: dotnet/issue-labeler/predict@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + issues: ${{ inputs.issues || github.event.issue.number }} + label_prefix: ${{ env.LABEL_PREFIX }} + threshold: ${{ env.THRESHOLD }} + env: + GITHUB_TOKEN: ${{ github.token }} + continue-on-error: ${{ !env.ALLOW_FAILURE }} diff --git a/.github/workflows/labeler-predict-pulls.yml b/.github/workflows/labeler-predict-pulls.yml index 8770da131520..9fae31e42bc1 100644 --- a/.github/workflows/labeler-predict-pulls.yml +++ b/.github/workflows/labeler-predict-pulls.yml @@ -1,4 +1,10 @@ -name: "Labeler: Predict Pull Labels" +# Workflow template imported and updated from: +# https://github.com/dotnet/issue-labeler/wiki/Onboarding +# +# See labeler.md for more information +# +# Predict labels for Pull Requests using a trained model +name: "Labeler: Predict (Pulls)" on: # Per to the following documentation: @@ -13,30 +19,53 @@ on: # Only automatically predict area labels when pull requests are first opened pull_request_target: types: opened + + # Configure the branches that need to have PRs labeled branches: - - 'main' + - main # Allow dispatching the workflow via the Actions UI, specifying ranges of numbers workflow_dispatch: inputs: - pull_numbers: - description: "Pull Numbers (comma-separated list of ranges)" - type: string - model_cache_key: - description: "The cache key suffix to use for loading the model" - type: string + pulls: + description: "Pull Request Numbers (comma-separated list of ranges)." + required: true + cache_key: + description: "The cache key suffix to use for restoring the model. Defaults to 'ACTIVE'." required: true - default: "LIVE" + default: "ACTIVE" + +env: + # Do not allow failure for jobs triggered automatically (this can block PR merge) + ALLOW_FAILURE: ${{ github.event_name == 'workflow_dispatch' }} + + LABEL_PREFIX: "Area-" + THRESHOLD: 0.40 jobs: - predict-pulls: - # Do not run the workflow on forks outside the 'dotnet' org - if: ${{ github.repository_owner == 'dotnet' && (inputs.pull_numbers || github.event.number) }} + predict-pull-label: + # Do not automatically run the workflow on forks outside the 'dotnet' org + if: ${{ github.event_name == 'workflow_dispatch' || github.repository_owner == 'dotnet' }} + runs-on: ubuntu-latest permissions: pull-requests: write - uses: dotnet/issue-labeler/.github/workflows/predict-pulls.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 - with: - model_cache_key: ${{ inputs.model_cache_key }} - pull_numbers: ${{ inputs.pull_numbers || github.event.number }} - label_prefix: "Area-" - threshold: 0.40 + steps: + - name: "Restore pulls model from cache" + id: restore-model + uses: dotnet/issue-labeler/restore@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: pulls + fail-on-cache-miss: ${{ env.ALLOW_FAILURE }} + quiet: true + + - name: "Predict pull labels" + id: prediction + if: ${{ steps.restore-model.outputs.cache-hit == 'true' }} + uses: dotnet/issue-labeler/predict@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + pulls: ${{ inputs.pulls || github.event.number }} + label_prefix: ${{ env.LABEL_PREFIX }} + threshold: ${{ env.THRESHOLD }} + env: + GITHUB_TOKEN: ${{ github.token }} + continue-on-error: ${{ !env.ALLOW_FAILURE }} diff --git a/.github/workflows/labeler-promote.yml b/.github/workflows/labeler-promote.yml index a8c283880590..c01086c51779 100644 --- a/.github/workflows/labeler-promote.yml +++ b/.github/workflows/labeler-promote.yml @@ -1,42 +1,54 @@ -name: "Labeler: Promote Models" +# Workflow template imported and updated from: +# https://github.com/dotnet/issue-labeler/wiki/Onboarding +# +# See labeler.md for more information +# +# Promote a model from staging to 'ACTIVE', backing up the currently 'ACTIVE' model +name: "Labeler: Promotion" on: # Dispatched via the Actions UI, promotes the staged models from - # a staging slot into the prediction environment + # a staged slot into the prediction environment workflow_dispatch: inputs: - promote_issues: + issues: description: "Issues: Promote Model" type: boolean required: true - promote_pulls: + pulls: description: "Pulls: Promote Model" type: boolean required: true - model_cache_key: - description: "The cache key suffix to promote into the 'LIVE' cache" - type: string + staged_key: + description: "The cache key suffix to use for promoting a staged model to 'ACTIVE'. Defaults to 'staged'." required: true - default: "staging" - backup_cache_key: - description: "The cache key suffix to use for backing up the currently promoted model" - type: string + default: "staged" + backup_key: + description: "The cache key suffix to use for backing up the currently active model. Defaults to 'backup'." default: "backup" permissions: actions: write jobs: - labeler-promote-issues: - if: ${{ inputs.promote_issues }} - uses: dotnet/issue-labeler/.github/workflows/promote-issues.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 - with: - model_cache_key: ${{ inputs.model_cache_key }} - backup_cache_key: ${{ inputs.backup_cache_key }} + promote-issues: + if: ${{ inputs.issues }} + runs-on: ubuntu-latest + steps: + - name: "Promote Model for Issues" + uses: dotnet/issue-labeler/promote@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "issues" + staged_key: ${{ inputs.staged_key }} + backup_key: ${{ inputs.backup_key }} - labeler-promote-pulls: - if: ${{ inputs.promote_pulls }} - uses: dotnet/issue-labeler/.github/workflows/promote-pulls.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 - with: - model_cache_key: ${{ inputs.model_cache_key }} - backup_cache_key: ${{ inputs.backup_cache_key }} \ No newline at end of file + promote-pulls: + if: ${{ inputs.pulls }} + runs-on: ubuntu-latest + steps: + - name: "Promote Model for Pull Requests" + uses: dotnet/issue-labeler/promote@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "pulls" + staged_key: ${{ inputs.staged_key }} + backup_key: ${{ inputs.backup_key }} diff --git a/.github/workflows/labeler-train.yml b/.github/workflows/labeler-train.yml index 6a318633388f..8c0fb0d8cfad 100644 --- a/.github/workflows/labeler-train.yml +++ b/.github/workflows/labeler-train.yml @@ -1,60 +1,161 @@ -name: "Labeler: Train Models" +# Workflow template imported and updated from: +# https://github.com/dotnet/issue-labeler/wiki/Onboarding +# +# See labeler.md for more information +# +# Train the Issues and Pull Requests models for label prediction +name: "Labeler: Training" on: - # Dispatched via the Actions UI, stages new models for promotion consideration - # Each step of the workflow can be run independently: Download, Train, and Test workflow_dispatch: inputs: - download_issues: - description: "Issues: Download Data" - type: boolean - default: true - train_issues: - description: "Issues: Train Model" - type: boolean - default: true - test_issues: - description: "Issues: Test Model" - type: boolean - default: true - download_pulls: - description: "Pulls: Download Data" - type: boolean - default: true - train_pulls: - description: "Pulls: Train Model" - type: boolean - default: true - test_pulls: - description: "Pulls: Test Model" - type: boolean - default: true - - data_limit: - description: "Max number of items to include in the model" - type: number + type: + description: "Issues or Pull Requests" + type: choice + required: true + default: "Both" + options: + - "Both" + - "Issues" + - "Pull Requests" + steps: + description: "Training Steps" + type: choice + required: true + default: "All" + options: + - "All" + - "Download Data" + - "Train Model" + - "Test Model" + + limit: + description: "Max number of items to download for training/testing the model (newest items are used). Defaults to the max number of pages times the page size." + type: number + page_size: + description: "Number of items per page in GitHub API requests. Defaults to 100 for issues, 25 for pull requests." + type: number + page_limit: + description: "Maximum number of pages to download for training/testing the model. Defaults to 1000 for issues, 4000 for pull requests." + type: number cache_key_suffix: - description: "The cache key suffix to use for staging data/models (use 'LIVE' to bypass staging)" - type: string + description: "The cache key suffix to use for staged data/models (use 'ACTIVE' to bypass staging). Defaults to 'staged'." required: true - default: "staging" + default: "staged" + +env: + CACHE_KEY: ${{ inputs.cache_key_suffix }} + REPOSITORY: ${{ github.repository }} + LABEL_PREFIX: "Area-" + THRESHOLD: "0.40" + LIMIT: ${{ inputs.limit }} + PAGE_SIZE: ${{ inputs.page_size }} + PAGE_LIMIT: ${{ inputs.page_limit }} jobs: - labeler-train: + download-issues: + if: ${{ contains(fromJSON('["Both", "Issues"]'), inputs.type) && contains(fromJSON('["All", "Download Data"]'), inputs.steps) }} + runs-on: ubuntu-latest + permissions: + issues: read + steps: + - name: "Download Issues" + uses: dotnet/issue-labeler/download@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "issues" + cache_key: ${{ env.CACHE_KEY }} + repository: ${{ env.REPOSITORY }} + label_prefix: ${{ env.LABEL_PREFIX }} + limit: ${{ env.LIMIT }} + page_size: ${{ env.PAGE_SIZE }} + page_limit: ${{ env.PAGE_LIMIT }} + env: + GITHUB_TOKEN: ${{ github.token }} + + download-pulls: + if: ${{ contains(fromJSON('["Both", "Pull Requests"]'), inputs.type) && contains(fromJSON('["All", "Download Data"]'), inputs.steps) }} + runs-on: ubuntu-latest + permissions: + pull-requests: read + steps: + - name: "Download Pull Requests" + uses: dotnet/issue-labeler/download@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "pulls" + cache_key: ${{ env.CACHE_KEY }} + repository: ${{ env.REPOSITORY }} + label_prefix: ${{ env.LABEL_PREFIX }} + limit: ${{ env.LIMIT }} + page_size: ${{ env.PAGE_SIZE }} + page_limit: ${{ env.PAGE_LIMIT }} + env: + GITHUB_TOKEN: ${{ github.token }} + + train-issues: + if: ${{ always() && contains(fromJSON('["Both", "Issues"]'), inputs.type) && contains(fromJSON('["All", "Train Model"]'), inputs.steps) && contains(fromJSON('["success", "skipped"]'), needs.download-issues.result) }} + runs-on: ubuntu-latest + permissions: {} + needs: download-issues + steps: + - name: "Train Model for Issues" + uses: dotnet/issue-labeler/train@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "issues" + data_cache_key: ${{ env.CACHE_KEY }} + model_cache_key: ${{ env.CACHE_KEY }} + + train-pulls: + if: ${{ always() && contains(fromJSON('["Both", "Pull Requests"]'), inputs.type) && contains(fromJSON('["All", "Train Model"]'), inputs.steps) && contains(fromJSON('["success", "skipped"]'), needs.download-pulls.result) }} + runs-on: ubuntu-latest + permissions: {} + needs: download-pulls + steps: + - name: "Train Model for Pull Requests" + uses: dotnet/issue-labeler/train@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "pulls" + data_cache_key: ${{ env.CACHE_KEY }} + model_cache_key: ${{ env.CACHE_KEY }} + + test-issues: + if: ${{ always() && contains(fromJSON('["Both", "Issues"]'), inputs.type) && contains(fromJSON('["All", "Test Model"]'), inputs.steps) && contains(fromJSON('["success", "skipped"]'), needs.train-issues.result) }} + runs-on: ubuntu-latest permissions: issues: read + needs: train-issues + steps: + - name: "Test Model for Issues" + uses: dotnet/issue-labeler/test@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "issues" + cache_key: ${{ env.CACHE_KEY }} + repository: ${{ env.REPOSITORY }} + label_prefix: ${{ env.LABEL_PREFIX }} + threshold: ${{ env.THRESHOLD }} + limit: ${{ env.LIMIT }} + page_size: ${{ env.PAGE_SIZE }} + page_limit: ${{ env.PAGE_LIMIT }} + env: + GITHUB_TOKEN: ${{ github.token }} + + test-pulls: + if: ${{ always() && contains(fromJSON('["Both", "Pull Requests"]'), inputs.type) && contains(fromJSON('["All", "Test Model"]'), inputs.steps) && contains(fromJSON('["success", "skipped"]'), needs.train-pulls.result) }} + runs-on: ubuntu-latest + permissions: pull-requests: read - actions: write - uses: dotnet/issue-labeler/.github/workflows/train.yml@f0c098669828a134c0313adf3f58c1909e555d86 # v1.0.1 - with: - download_issues: ${{ inputs.download_issues }} - train_issues: ${{ inputs.train_issues }} - test_issues: ${{ inputs.test_issues }} - download_pulls: ${{ inputs.download_pulls }} - train_pulls: ${{ inputs.train_pulls }} - test_pulls: ${{ inputs.test_pulls }} - data_limit: ${{ inputs.data_limit && fromJSON(inputs.data_limit) || 0 }} - cache_key_suffix: ${{ inputs.cache_key_suffix }} - label_prefix: "Area-" - threshold: 0.40 \ No newline at end of file + needs: train-pulls + steps: + - name: "Test Model for Pull Requests" + uses: dotnet/issue-labeler/test@46125e85e6a568dc712f358c39f35317366f5eed # v2.0.0 + with: + type: "pulls" + cache_key: ${{ env.CACHE_KEY }} + repository: ${{ env.REPOSITORY }} + label_prefix: ${{ env.LABEL_PREFIX }} + threshold: ${{ env.THRESHOLD }} + limit: ${{ env.LIMIT }} + page_size: ${{ env.PAGE_SIZE }} + page_limit: ${{ env.PAGE_LIMIT }} + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/labeler.md b/.github/workflows/labeler.md new file mode 100644 index 000000000000..940599e7fdeb --- /dev/null +++ b/.github/workflows/labeler.md @@ -0,0 +1,30 @@ +# Issue-Labeler Workflows + +This repository uses actions from [dotnet/issue-labeler](https://github.com/dotnet/issue-labeler) to predict area labels for issues and pull requests. + +The following workflow templates were imported and updated from [dotnet/issue-labeler/wiki/Onboarding](https://github.com/dotnet/issue-labeler/wiki/Onboarding): + +1. `labeler-cache-retention.yml` +2. `labeler-predict-issues.yml` +3. `labeler-predict-pulls.yml` +4. `labeler-promote.yml` +5. `labeler-train.yml` + +## Repository Configuration + +Across these workflows, the following changes were made to configure the issue labeler for this repository: + +1. Set `LABEL_PREFIX` to `"Area-"`: + - `labeler-predict-issues.yml` + - `labeler-predict-pulls.yml` + - `labeler-train.yml` +2. Remove the `DEFAULT_LABEL` value and input as we do not apply a default label in this repository when no prediction is made. + - `labeler-predict-issues.yml` + - `labeler-predict-pulls.yml` +3. Remove the `EXCLUDED_AUTHORS` value as we do not bypass labeling for any authors' issues/pulls in this repository: + - `labeler-predict-issues.yml` + - `labeler-predict-pulls.yml` +4. Remove the `repository` input for training the models against another repository: + - `labeler-train.yml` +5. Update the cache retention cron schedule to an arbitrary time of day: + - `labeler-cache-retention.yml`