Fixes #22967: move auto-assigned incidents to the Assigned stage #15976
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright 2021 Collate | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| name: UI Checkstyle | |
| on: | |
| merge_group: | |
| # Note: paths filter removed — the workflow always triggers so that the | |
| # required status check (report) always completes. Path filtering is handled | |
| # inside the workflow via dorny/paths-filter so PRs without UI changes skip | |
| # the expensive jobs while still reporting a passing status. | |
| pull_request_target: | |
| types: | |
| - opened | |
| - synchronize | |
| - reopened | |
| - ready_for_review | |
| - labeled | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ui-checkstyle-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: ${{ github.event_name != 'pull_request_target' || github.event.action != 'labeled' || github.event.label.name == 'safe to test' }} | |
| env: | |
| UI_WORKING_DIRECTORY: openmetadata-ui/src/main/resources/ui | |
| CORE_COMPONENTS_WORKING_DIRECTORY: openmetadata-ui-core-components/src/main/resources/ui | |
| jobs: | |
| check-changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| ui-changed: ${{ steps.filter.outputs.ui }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| if: ${{ github.event_name == 'merge_group' }} | |
| with: | |
| fetch-depth: 0 | |
| filter: blob:none | |
| persist-credentials: false | |
| - uses: dorny/paths-filter@v4 | |
| id: filter | |
| with: | |
| base: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_sha || '' }} | |
| filters: | | |
| ui: | |
| - 'openmetadata-ui/src/main/resources/ui/**' | |
| - 'openmetadata-spec/src/main/resources/json/schema/**' | |
| - '.github/workflows/ui-checkstyle.yml' | |
| - 'openmetadata-ui-core-components/src/main/resources/ui/**' | |
| authorize: | |
| needs: check-changes | |
| if: | | |
| needs.check-changes.outputs.ui-changed == 'true' && | |
| (github.event_name != 'pull_request_target' || | |
| (github.event.action != 'labeled' || github.event.label.name == 'safe to test')) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Wait for the labeler | |
| uses: lewagon/wait-on-check-action@v1.7.0 | |
| if: ${{ github.event_name == 'pull_request_target' }} | |
| with: | |
| ref: ${{ github.event_name == 'merge_group' && github.sha || github.event.pull_request.head.sha }} | |
| check-name: Team Label | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| wait-interval: 90 | |
| - name: Verify PR labels | |
| uses: jesusvasquez333/verify-pr-label-action@v1.4.0 | |
| if: ${{ github.event_name == 'pull_request_target' }} | |
| with: | |
| github-token: "${{ secrets.GITHUB_TOKEN }}" | |
| valid-labels: "safe to test" | |
| pull-request-number: "${{ github.event.pull_request.number }}" | |
| disable-reviews: true | |
| checkstyle: | |
| needs: authorize | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| lint_src_result: ${{ steps.lint_src.outcome }} | |
| lint_src_changed_files: ${{ steps.lint_src.outputs.changed_files }} | |
| license_result: ${{ steps.license.outcome }} | |
| license_changed_files: ${{ steps.license.outputs.changed_files }} | |
| i18n_result: ${{ steps.i18n.outcome }} | |
| i18n_changed_files: ${{ steps.i18n.outputs.changed_files }} | |
| app_docs_result: ${{ steps.app_docs.outcome }} | |
| app_docs_changed_files: ${{ steps.app_docs.outputs.changed_files }} | |
| lint_playwright_result: ${{ steps.lint_playwright.outcome }} | |
| lint_playwright_changed_files: ${{ steps.lint_playwright.outputs.changed_files }} | |
| lint_core_components_result: ${{ steps.lint_core_components.outcome }} | |
| lint_core_components_changed_files: ${{ steps.lint_core_components.outputs.changed_files }} | |
| tw_audit_result: ${{ steps.tw_audit.outcome }} | |
| tw_audit_changed_files: ${{ steps.tw_audit.outputs.changed_files }} | |
| tw_guard_result: ${{ steps.tw_guard.outcome }} | |
| tw_guard_changed_files: ${{ steps.tw_guard.outputs.changed_files }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event_name == 'merge_group' && github.sha || github.event.pull_request.head.sha }} | |
| allow-unsafe-pr-checkout: true | |
| fetch-depth: 0 | |
| filter: blob:none | |
| persist-credentials: false | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version-file: "${{ env.UI_WORKING_DIRECTORY }}/.nvmrc" | |
| cache: yarn | |
| cache-dependency-path: | | |
| ${{ env.UI_WORKING_DIRECTORY }}/yarn.lock | |
| ${{ env.CORE_COMPONENTS_WORKING_DIRECTORY }}/yarn.lock | |
| - name: Install Antlr4 CLI | |
| run: sudo make install_antlr_cli | |
| - name: Install UI Yarn Packages | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| run: yarn install --frozen-lockfile | |
| - name: Get changed src files | |
| id: changed-src-files | |
| uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 | |
| with: | |
| path: ${{ env.UI_WORKING_DIRECTORY }} | |
| files_ignore: | | |
| src/generated/** | |
| files: | | |
| src/**/*.{ts,tsx,js,jsx,json} | |
| - name: ESLint + Prettier + Organise Imports (src) | |
| id: lint_src | |
| if: steps.changed-src-files.outputs.any_changed == 'true' | |
| continue-on-error: true | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| env: | |
| CHANGED_FILES: ${{ steps.changed-src-files.outputs.all_changed_files }} | |
| run: | | |
| if [ -z "$CHANGED_FILES" ]; then | |
| echo "No added or modified files to process." | |
| exit 0 | |
| fi | |
| TS_FILES=$(echo "$CHANGED_FILES" | tr ' ' '\n' | awk '/\.(ts|tsx|js|jsx)$/ { printf "%s ", $0 }') | |
| if [ -n "$TS_FILES" ]; then | |
| yarn organize-imports:cli $TS_FILES | |
| fi | |
| yarn lint:base --fix $CHANGED_FILES | |
| yarn pretty:base --write $CHANGED_FILES | |
| if [ -n "$(git status --porcelain)" ]; then | |
| FILES=$(git status --porcelain | awk '{print " - `" $2 "`"}' | head -30) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$FILES" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| git checkout -- . | |
| git clean -fd | |
| exit 1 | |
| fi | |
| - name: Get all changed UI files | |
| id: changed-ui-files | |
| uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 | |
| with: | |
| path: ${{ env.UI_WORKING_DIRECTORY }} | |
| - name: Licence Header Check | |
| id: license | |
| if: steps.changed-ui-files.outputs.any_changed == 'true' | |
| continue-on-error: true | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| env: | |
| CHANGED_FILES_ALL: ${{ steps.changed-ui-files.outputs.all_changed_files }} | |
| run: | | |
| if [ -z "$CHANGED_FILES_ALL" ]; then | |
| echo "No added or modified files to process." | |
| exit 0 | |
| fi | |
| yarn license-header-fix $CHANGED_FILES_ALL | |
| if [ -n "$(git status --porcelain)" ]; then | |
| FILES=$(git status --porcelain | awk '{print " - `" $2 "`"}' | head -30) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$FILES" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| git checkout -- . | |
| git clean -fd | |
| exit 1 | |
| fi | |
| - name: I18n Sync | |
| id: i18n | |
| continue-on-error: true | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| run: | | |
| yarn i18n | |
| if [ -n "$(git status --porcelain)" ]; then | |
| FILES=$(git status --porcelain | awk '{print " - `" $2 "`"}' | head -20) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$FILES" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| git checkout -- . | |
| git clean -fd | |
| exit 1 | |
| fi | |
| - name: generate:app-docs | |
| id: app_docs | |
| continue-on-error: true | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| run: | | |
| yarn generate:app-docs | |
| if [ -n "$(git status --porcelain)" ]; then | |
| FILES=$(git status --porcelain | awk '{print " - `" $2 "`"}' | head -20) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$FILES" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| git checkout -- . | |
| git clean -fd | |
| exit 1 | |
| fi | |
| - name: Get changed Playwright files | |
| id: changed-playwright-files | |
| uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 | |
| with: | |
| path: ${{ env.UI_WORKING_DIRECTORY }} | |
| files_ignore: | | |
| playwright/test-data/** | |
| files: | | |
| playwright/**/*.{ts,tsx,js,jsx} | |
| - name: ESLint + Prettier + Organise Imports (playwright) | |
| id: lint_playwright | |
| if: steps.changed-playwright-files.outputs.any_changed == 'true' | |
| continue-on-error: true | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| env: | |
| CHANGED_FILES: ${{ steps.changed-playwright-files.outputs.all_changed_files }} | |
| run: | | |
| if [ -z "$CHANGED_FILES" ]; then | |
| echo "No added or modified files to process." | |
| exit 0 | |
| fi | |
| yarn organize-imports:cli $CHANGED_FILES | |
| yarn lint:base --fix $CHANGED_FILES | |
| yarn pretty:base --write $CHANGED_FILES | |
| if [ -n "$(git status --porcelain)" ]; then | |
| FILES=$(git status --porcelain | awk '{print " - `" $2 "`"}' | head -30) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$FILES" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| git checkout -- . | |
| git clean -fd | |
| exit 1 | |
| fi | |
| - name: Install Core Components Yarn Packages | |
| working-directory: ${{ env.CORE_COMPONENTS_WORKING_DIRECTORY }} | |
| run: yarn install --frozen-lockfile | |
| - name: Get changed core-components files | |
| id: changed-core-components-files | |
| uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 | |
| with: | |
| path: ${{ env.CORE_COMPONENTS_WORKING_DIRECTORY }} | |
| files: | | |
| src/**/*.{ts,tsx,js,jsx,json} | |
| - name: ESLint + Prettier (core-components) | |
| id: lint_core_components | |
| if: steps.changed-core-components-files.outputs.any_changed == 'true' | |
| continue-on-error: true | |
| working-directory: ${{ env.CORE_COMPONENTS_WORKING_DIRECTORY }} | |
| env: | |
| CHANGED_FILES: ${{ steps.changed-core-components-files.outputs.all_changed_files }} | |
| run: | | |
| if [ -z "${CHANGED_FILES// }" ]; then | |
| echo "No added or modified files to process." | |
| exit 0 | |
| fi | |
| yarn lint:base --fix $CHANGED_FILES | |
| yarn pretty:base --write $CHANGED_FILES | |
| if [ -n "$(git status --porcelain)" ]; then | |
| FILES=$(git status --porcelain | awk '{print " - `" $2 "`"}' | head -30) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$FILES" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| git checkout -- . | |
| git clean -fd | |
| exit 1 | |
| fi | |
| - name: Tailwind Audit (no hardcoded values) | |
| id: tw_audit | |
| if: steps.changed-src-files.outputs.any_changed == 'true' | |
| continue-on-error: true | |
| working-directory: ${{ env.UI_WORKING_DIRECTORY }} | |
| env: | |
| CHANGED_FILES: ${{ steps.changed-src-files.outputs.all_changed_files }} | |
| run: | | |
| TS_FILES=$(echo "$CHANGED_FILES" | tr ' ' '\n' | awk '/\.(ts|tsx|js|jsx)$/ { printf "%s ", $0 }') | |
| if [ -z "${TS_FILES// }" ]; then | |
| echo "No TSX/TS files to audit." | |
| exit 0 | |
| fi | |
| if ! node scripts/tw-audit.js $TS_FILES > /tmp/tw-audit.out 2>&1; then | |
| cat /tmp/tw-audit.out | |
| OUT=$(sed 's/\x1b\[[0-9;]*m//g' /tmp/tw-audit.out | grep -E 'errors|Files with|^ +[0-9]' | head -30 | sed 's/^/ /') | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$OUT" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| - name: Antd + Less Deprecation Guard (no new debt) | |
| id: tw_guard | |
| if: steps.changed-ui-files.outputs.any_changed == 'true' | |
| continue-on-error: true | |
| env: | |
| BASE_SHA: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_sha || github.event.pull_request.base.sha }} | |
| run: | | |
| if ! node ${{ env.UI_WORKING_DIRECTORY }}/scripts/tw-deprecation-guard.js "$BASE_SHA" > /tmp/tw-guard.out 2>&1; then | |
| cat /tmp/tw-guard.out | |
| OUT=$(sed 's/\x1b\[[0-9;]*m//g' /tmp/tw-guard.out | grep -E '^ ' | head -30) | |
| echo "changed_files<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$OUT" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| ui-checkstyle: | |
| needs: [authorize, checkstyle] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: Find existing summary comment | |
| uses: peter-evans/find-comment@v4 | |
| id: fc | |
| if: ${{ github.event_name == 'pull_request_target' }} | |
| continue-on-error: true | |
| with: | |
| issue-number: ${{ github.event.pull_request.number }} | |
| comment-author: github-actions[bot] | |
| body-includes: '<!-- check:ui-checkstyle-summary -->' | |
| - name: Post or update summary comment | |
| uses: actions/github-script@v8 | |
| if: ${{ github.event_name == 'pull_request_target' && steps.fc.outcome == 'success' }} | |
| continue-on-error: true | |
| with: | |
| script: | | |
| const checks = [ | |
| { | |
| name: 'ESLint + Prettier + Organise Imports (src)', | |
| reason: 'One or more source files have linting or formatting issues.', | |
| result: '${{ needs.checkstyle.outputs.lint_src_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.lint_src_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'Licence Header', | |
| reason: 'One or more files are missing or have an outdated Apache 2.0 licence header.', | |
| result: '${{ needs.checkstyle.outputs.license_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.license_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'I18n Sync', | |
| reason: 'Translation locale files are out of sync with `en-us.json`.', | |
| result: '${{ needs.checkstyle.outputs.i18n_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.i18n_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'App Docs', | |
| reason: 'Generated application docs are stale and need to be regenerated.', | |
| result: '${{ needs.checkstyle.outputs.app_docs_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.app_docs_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'Playwright - ESLint + Prettier + Organise Imports', | |
| reason: 'One or more Playwright test files have linting or formatting issues.', | |
| result: '${{ needs.checkstyle.outputs.lint_playwright_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.lint_playwright_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'Core Components - ESLint + Prettier', | |
| reason: 'One or more core-component files have linting or formatting issues.', | |
| result: '${{ needs.checkstyle.outputs.lint_core_components_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.lint_core_components_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'Tailwind Audit', | |
| reason: 'Hardcoded Tailwind values found. Use a design-system utility (run `yarn tw-audit:report` for the token each value maps to).', | |
| result: '${{ needs.checkstyle.outputs.tw_audit_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.tw_audit_changed_files) }} || '', | |
| }, | |
| { | |
| name: 'Antd + Less Deprecation Guard', | |
| reason: 'A new `antd` import or new `.less` file was added. Use UntitledUI + Tailwind for new work.', | |
| result: '${{ needs.checkstyle.outputs.tw_guard_result }}', | |
| files: ${{ toJSON(needs.checkstyle.outputs.tw_guard_changed_files) }} || '', | |
| }, | |
| ]; | |
| const failures = checks.filter(c => c.result === 'failure'); | |
| const commentId = '${{ steps.fc.outputs.comment-id }}'; | |
| if (failures.length === 0) { | |
| if (commentId) { | |
| await github.rest.issues.deleteComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: parseInt(commentId, 10), | |
| }); | |
| } | |
| return; | |
| } | |
| const sections = failures.map(c => { | |
| const lines = [`#### ❌ ${c.name}`, c.reason]; | |
| if (c.files && c.files.trim()) { | |
| lines.push('', '<details><summary>Affected files</summary>', '', c.files.trim(), '', '</details>'); | |
| } | |
| return lines.join('\n'); | |
| }); | |
| const body = [ | |
| '<!-- check:ui-checkstyle-summary -->', | |
| '### ❌ UI Checkstyle Failed', | |
| '', | |
| ...sections.flatMap(s => [s, '']), | |
| '---', | |
| '**Fix locally (fast - only checks files changed in this branch):**', | |
| '```bash', | |
| 'make ui-checkstyle-changed', | |
| '```', | |
| ].join('\n'); | |
| if (commentId) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: parseInt(commentId, 10), | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| } | |
| - name: Check final results | |
| if: always() | |
| run: | | |
| checkstyle_result="${{ needs.checkstyle.result }}" | |
| if [[ "$checkstyle_result" != "success" && "$checkstyle_result" != "skipped" ]]; then | |
| echo "Checkstyle job ended with status: $checkstyle_result" | |
| exit 1 | |
| fi | |
| if [ "${{ needs.checkstyle.outputs.lint_src_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.license_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.i18n_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.app_docs_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.lint_playwright_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.lint_core_components_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.tw_audit_result }}" = 'failure' ] || \ | |
| [ "${{ needs.checkstyle.outputs.tw_guard_result }}" = 'failure' ]; then | |
| echo "One or more checks failed." | |
| exit 1 | |
| fi | |
| echo "All checks passed or were not required for this PR." |