GHA Overhaul #18
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
| name: PR Validation | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| paths-ignore: | |
| - 'docs/**' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| # Inline setup - required for fork PR compatibility | |
| # Cannot use ./.github/actions/setup-pnpm as it won't work from forks | |
| - uses: pnpm/action-setup@v4 | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile --prefer-offline | |
| - name: Cache Manifest | |
| uses: actions/cache@v4 | |
| with: | |
| path: manifest-cache | |
| key: destiny-manifest-${{ github.run_number }} | |
| restore-keys: | | |
| destiny-manifest- | |
| - name: Run tests | |
| run: pnpm test | |
| env: | |
| CLEAN_MANIFEST_CACHE: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: success() || failure() | |
| with: | |
| name: test-results | |
| path: junit.xml | |
| retention-days: 7 | |
| lint: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| # Inline setup - required for fork PR compatibility | |
| - uses: pnpm/action-setup@v4 | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile --prefer-offline | |
| # Optimized cache key: Only invalidate on config changes, not all dependencies | |
| - name: Cache ESLint | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| .eslintcache | |
| node_modules/.cache | |
| key: ${{ runner.os }}-eslint-${{ hashFiles('eslint.config.js', 'tsconfig.json') }}-${{ hashFiles('src/**/*.ts', 'src/**/*.tsx', 'src/**/*.js', 'src/**/*.jsx') }} | |
| restore-keys: | | |
| ${{ runner.os }}-eslint-${{ hashFiles('eslint.config.js', 'tsconfig.json') }}- | |
| ${{ runner.os }}-eslint- | |
| - name: Prettier | |
| run: pnpm lint:prettier | |
| - name: StyleLint | |
| run: pnpm lint:stylelint | |
| - name: ESLint | |
| id: eslint | |
| run: pnpm lint-report:cached | |
| continue-on-error: true | |
| - name: Upload ESLint results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: eslint-results | |
| path: eslint.results.json | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| # Annotation happens in separate workflow (pr-reports.yml) | |
| # This allows annotations to work for fork PRs too | |
| - name: Fail if ESLint has errors | |
| if: steps.eslint.outcome == 'failure' | |
| run: | | |
| pnpm lintcached | |
| exit 1 | |
| build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| environment: | |
| name: pr | |
| url: ${{ steps.deploy-url.outputs.url }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| # Inline setup - required for fork PR compatibility | |
| - uses: pnpm/action-setup@v4 | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile --prefer-offline | |
| - name: Get package version | |
| id: package-version | |
| uses: martinbeentjes/[email protected] | |
| - name: Set version | |
| run: | | |
| echo "VERSION=${{ steps.package-version.outputs.current-version }}.${{ github.run_number }}" >> $GITHUB_ENV | |
| - name: Build PR version | |
| run: pnpm build:pr | |
| env: | |
| NODE_OPTIONS: "--max_old_space_size=8192" | |
| WEB_API_KEY: ${{ secrets.BUNGIE_API_KEY }} | |
| WEB_OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }} | |
| WEB_OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_SECRET }} | |
| DIM_API_KEY: ${{ secrets.DIM_API_KEY }} | |
| PUBLIC_PATH: /${{ github.event.number }}/ | |
| - name: Check for build pipeline updates | |
| id: filter | |
| uses: dorny/paths-filter@v3 | |
| with: | |
| filters: | | |
| build-pipeline: | |
| - package.json | |
| - pnpm-lock.yaml | |
| - config/webpack.ts | |
| - babel.config.cjs | |
| - name: Upload webpack stats | |
| if: steps.filter.outputs.build-pipeline == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: webpack-stats | |
| path: webpack-stats.json | |
| retention-days: 1 | |
| - name: Install SSH key | |
| if: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' }} | |
| uses: benoitchantre/[email protected] | |
| with: | |
| private-key: ${{ secrets.SSH_KEY }} | |
| private-key-name: dim.rsa | |
| known-hosts: ${{ secrets.REMOTE_HOST }} | |
| - name: Check Syntax | |
| if: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' }} | |
| run: pnpm syntax | |
| - name: Deploy to preview | |
| if: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' }} | |
| run: ./build/rsync-deploy.sh | |
| env: | |
| SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }} | |
| SOURCE: "dist/" | |
| REMOTE_USER: ${{ secrets.REMOTE_USER }} | |
| REMOTE_HOST: ${{ secrets.REMOTE_HOST }} | |
| REMOTE_PATH: pr.destinyitemmanager.com/${{ github.event.number }} | |
| - name: Purge CloudFlare cache | |
| if: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' }} | |
| run: ./build/purge-cloudflare.sh | |
| env: | |
| CLOUDFLARE_KEY: ${{ secrets.CLOUDFLARE_KEY }} | |
| CLOUDFLARE_EMAIL: ${{ secrets.CLOUDFLARE_EMAIL }} | |
| APP_DOMAIN: pr.destinyitemmanager.com/${{ github.event.number }} | |
| - name: Set preview URL | |
| if: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' }} | |
| id: deploy-url | |
| run: | | |
| echo "url=https://pr.dim.gg/${{ github.event.number }}/" >> $GITHUB_OUTPUT |