All skills
secondsky avatar

/sapui5-linter

@620a19a
by Eddiesecondsky/sap-skills456 stars
120

Use this skill when working with the UI5 Linter (@ui5/linter) for static code analysis of SAPUI5/OpenUI5 applications and libraries. Covers setup, configuring linting rules, running the linter to detect deprecated APIs, global variable usage, CSP violations, and manifest issues. Supports autofix for deprecated API usage, global references, event handlers, and manifest properties. Includes CI/CD integration, pre-commit hooks, and UI5 2.x migration preparation.

Use this Skill: https://skilld.dev/gh/secondsky/sap-skills/sapui5-linter

This session only. Nothing lands on disk.

referencesadvanced-ci-cd.md

≈4.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

UI5 Linter - Advanced CI/CD Integration

Source: https://github.com/UI5/linter/blob/main/.github/workflows/ci.yml Last Updated: 2025-11-21 UI5 Linter Version: 1.22.0


Overview

This guide covers advanced CI/CD integration patterns for UI5 Linter, including the UI5 Linter project's own CI workflow, coverage reporting, license checking, dependency analysis, and multi-environment strategies.


UI5 Linter's Own CI Workflow (Real-World Example)

The UI5 Linter project itself uses a comprehensive CI pipeline that demonstrates best practices.

Complete Workflow

File: .github/workflows/ci.yml

Note: This is the actual CI workflow used by the UI5 Linter project itself, demonstrating production best practices.

name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

permissions: {}

jobs:
  test:
    name: Test
    runs-on: ubuntu-24.04

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci --engine-strict

      - name: Run linter
        run: npm run lint

      - name: Check licenses
        run: npm run check-licenses

      - name: Check dependencies
        run: npm run depcheck

      - name: Build
        run: npm run build-test

      - name: Run tests with coverage
        run: npm run coverage

      - name: Report coverage
        uses: coverallsapp/github-action@v2.3.6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
        continue-on-error: true

Key Patterns Demonstrated

1. Engine-Strict Installation

- name: Install dependencies
  run: npm ci --engine-strict

Why: Fails fast if Node.js version is incompatible, preventing hidden issues.


2. Multi-Step Quality Checks

- run: npm run lint        # Code quality
- run: npm run check-licenses  # Legal compliance
- run: npm run depcheck    # Dependency health
- run: npm run build-test  # Build verification
- run: npm run coverage    # Test coverage

Why: Layered validation catches different types of issues.


3. Coverage Reporting

- uses: coverallsapp/github-action@v2.3.6
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
  continue-on-error: true

Why: continue-on-error prevents workflow failure if Coveralls is down.


4. Minimal Permissions

permissions: {}

Why: Security best practice - grant only necessary permissions.


Advanced GitHub Actions Patterns

Multi-Platform Testing

Test across operating systems:

name: Cross-Platform Lint

on: [push, pull_request]

jobs:
  lint:
    strategy:
      matrix:
        os: [ubuntu-24.04, macos-latest, windows-latest]
        node: ['24', '22']

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: ${{ matrix.node }}
          cache: 'npm'

      - run: npm ci

      - name: Run UI5 Linter
        run: npm run lint

Use Cases:

  • Ensure linter works on all platforms
  • Catch platform-specific path issues
  • Verify compatibility with multiple Node versions

Multi-Job Workflow with Dependencies

Organize checks into separate jobs:

name: Complete Validation

on: [push, pull_request]

jobs:
  lint-ui5:
    name: UI5 Linter
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint

  lint-js:
    name: ESLint
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
      - run: npm ci
      - run: npm run eslint

  test:
    name: Tests
    needs: [lint-ui5, lint-js]  # Only run if linting passes
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
      - run: npm ci
      - run: npm test

  deploy:
    name: Deploy
    needs: test  # Only deploy if tests pass
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - run: echo "Deploy to production"

Benefits:

  • Parallel execution (faster)
  • Clear separation of concerns
  • Conditional deployment

Caching for Performance

Optimize workflow performance with caching:

jobs:
  lint:
    runs-on: ubuntu-24.04

    steps:
      - uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'  # Automatic npm cache

      - name: Cache UI5 Linter results
        uses: actions/cache@v4
        with:
          path: .ui5lint-cache
          key: ui5lint-${{ hashFiles('webapp/**/*.js', 'webapp/**/*.xml', 'ui5lint.config.*') }}
          restore-keys: |
            ui5lint-

      - run: npm ci

      - name: Run UI5 Linter
        run: npm run lint

Performance Gain: 30-50% faster on cache hit


Diff-Based Linting (Lint Only Changed Files)

Lint only files changed in PR:

name: Incremental Lint

on: [pull_request]

jobs:
  lint-changed:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0  # Fetch all history for diff

      - uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci

      - name: Get changed files
        id: changed-files
        run: |
          echo "files=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -E '\.(js|xml|json)$' | tr '\n' ' ')" >> $GITHUB_OUTPUT

      - name: Lint changed files
        if: steps.changed-files.outputs.files != ''
        run: |
          npx ui5lint ${{ steps.changed-files.outputs.files }}

Benefits:

  • Faster on large codebases
  • Immediate feedback on changes

Coverage Reporting Integration

Coveralls Integration

Setup:

npm install --save-dev nyc

package.json:

{
  "scripts": {
    "test": "ava",
    "coverage": "nyc npm test",
    "lint": "ui5lint"
  },
  "nyc": {
    "reporter": ["lcov", "text"],
    "include": ["src/**/*.js"],
    "exclude": ["test/**"]
  }
}

GitHub Actions:

- name: Run tests with coverage
  run: npm run coverage

- name: Upload to Coveralls
  uses: coverallsapp/github-action@v2.3.6
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
  continue-on-error: true

Codecov Integration

- name: Run tests with coverage
  run: npm run coverage

- name: Upload to Codecov
  uses: codecov/codecov-action@v3
  with:
    files: ./coverage/lcov.info
    flags: unittests
    name: codecov-umbrella
    fail_ci_if_error: true

License Checking

Ensure all dependencies have acceptable licenses:

package.json:

{
  "scripts": {
    "check-licenses": "license-checker --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC'"
  },
  "devDependencies": {
    "license-checker": "^25.0.1"
  }
}

GitHub Actions:

- name: Check licenses
  run: npm run check-licenses

Why: Legal compliance, prevent GPL contamination


Dependency Checking

Identify unused or missing dependencies:

package.json:

{
  "scripts": {
    "depcheck": "depcheck --ignores='@types/*,eslint-*'"
  },
  "devDependencies": {
    "depcheck": "^1.4.3"
  }
}

GitHub Actions:

- name: Check dependencies
  run: npm run depcheck

Why: Keep dependencies clean, reduce bundle size


Security Scanning

npm audit

- name: Security audit
  run: npm audit --audit-level=moderate
  continue-on-error: true  # Don't fail on low/moderate

Snyk Integration

- name: Run Snyk
  uses: snyk/actions/node@master
  env:
    SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
  with:
    args: --severity-threshold=high

Artifact Management

Save lint results as artifacts:

jobs:
  lint:
    runs-on: ubuntu-24.04

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
      - run: npm ci

      - name: Run UI5 Linter (JSON output)
        run: npm run lint -- --format json 2> lint-diagnostics.log | tee lint-results.json
        continue-on-error: true

      - name: Run UI5 Linter (HTML report)
        run: npm run lint -- --format html 2> lint-diagnostics.log | tee lint-report.html
        continue-on-error: true

      - name: Upload JSON results
        uses: actions/upload-artifact@v5
        if: always()
        with:
          name: lint-results-json
          path: lint-results.json
          retention-days: 30

      - name: Upload HTML report
        uses: actions/upload-artifact@v5
        if: always()
        with:
          name: lint-report-html
          path: lint-report.html
          retention-days: 30

      - name: Check for errors
        run: |
          if [ ! -f lint-results.json ]; then
            echo "❌ Lint results file not found"
            exit 1
          fi
          if ! jq '[.[].errorCount] | add' lint-results.json > /tmp/error_count 2>/dev/null; then
            echo "❌ Failed to parse lint-results.json"
            exit 1
          fi
          ERROR_COUNT=$(cat /tmp/error_count)
          ERROR_COUNT=${ERROR_COUNT:-0}
          if [ "$ERROR_COUNT" -gt 0 ]; then
            echo "❌ Found $ERROR_COUNT linting errors"
            exit 1
          fi

Benefits:

  • Download reports for review
  • Historical tracking
  • Share with non-technical stakeholders (HTML)

Pull Request Comments

Add lint results as PR comments:

jobs:
  lint-pr:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci

      - name: Run UI5 Linter
        id: lint
        run: |
          npm run lint -- --format markdown > lint-results.md || true
          echo "results<<EOF" >> $GITHUB_OUTPUT
          cat lint-results.md >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Comment PR
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.name,
              body: '## UI5 Lint Results\n\n${{ steps.lint.outputs.results }}'
            })

GitLab CI Integration

File: .gitlab-ci.yml

stages:
  - lint
  - test
  - deploy

variables:
  npm_config_cache: "$CI_PROJECT_DIR/.npm"

cache:
  paths:
    - .npm
    - node_modules

lint:ui5:
  stage: lint
  image: node:20
  script:
    - npm ci
    - npm run lint -- --format json > lint-results.json
    - npm run lint -- --format html > lint-report.html
  artifacts:
    when: always
    reports:
      junit: lint-results.json
    paths:
      - lint-report.html
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == "main"'

lint:ui5:fix:
  stage: lint
  image: node:20
  script:
    - npm ci
    - npm run lint:fix
    - git diff --exit-code || (echo "Autofix available" && exit 1)
  allow_failure: true
  only:
    - merge_requests

Jenkins Pipeline

File: Jenkinsfile

pipeline {
    agent {
        docker {
            image 'node:20'
        }
    }

    stages {
        stage('Install') {
            steps {
                sh 'npm ci'
            }
        }

        stage('Lint') {
            steps {
                sh 'npm run lint -- --format json > lint-results.json'
                sh 'npm run lint -- --format html > lint-report.html'
            }
            post {
                always {
                    archiveArtifacts artifacts: 'lint-*.json,lint-*.html', allowEmptyArchive: true
                    publishHTML([
                        reportDir: '.',
                        reportFiles: 'lint-report.html',
                        reportName: 'UI5 Lint Report'
                    ])
                }
            }
        }

        stage('Test') {
            when {
                expression {
                    def results = readJSON file: 'lint-results.json'
                    return results.sum { it.errorCount } == 0
                }
            }
            steps {
                sh 'npm test'
            }
        }
    }
}

Pre-Commit Hooks (Advanced)

Lint-Staged with Auto-Fix

package.json:

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "webapp/**/*.{js,xml}": [
      "ui5lint --fix",
      "ui5lint",
      "git add"
    ],
    "webapp/manifest.json": [
      "ui5lint --fix",
      "ui5lint"
    ]
  }
}

Setup:

npm install --save-dev husky lint-staged
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"

Commit Message Linting

Enforce conventional commits (like UI5 Linter):

package.json:

{
  "devDependencies": {
    "@commitlint/cli": "^17.0.0",
    "@commitlint/config-conventional": "^17.0.0"
  }
}

commitlint.config.mjs:

export default {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore'
    ]],
    'scope-enum': [2, 'always', [
      'linter', 'autofix', 'docs', 'ci'
    ]]
  }
};

Husky Hook:

npx husky add .husky/commit-msg "npx commitlint --edit $1"

Monorepo Integration

For monorepos with multiple UI5 apps:

name: Monorepo Lint

on: [push, pull_request]

jobs:
  find-apps:
    runs-on: ubuntu-24.04
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v6
      - id: set-matrix
        run: |
          APPS=$(find apps -name "ui5.yaml" -exec dirname {} \; | jq -R -s -c 'split("\n")[:-1]')
          echo "matrix=$APPS" >> $GITHUB_OUTPUT

  lint:
    needs: find-apps
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        app: ${{ fromJson(needs.find-apps.outputs.matrix) }}
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
          cache-dependency-path: '${{ matrix.app }}/package-lock.json'

      - name: Install dependencies
        run: npm ci
        working-directory: ${{ matrix.app }}

      - name: Lint ${{ matrix.app }}
        run: npm run lint
        working-directory: ${{ matrix.app }}

Environment-Specific Configurations

Use different configs for dev vs CI:

ui5lint.config.js (dev):

export default {
  ignores: ["webapp/thirdparty/**"]
};

.ui5lint.ci.config.js (CI):

export default {
  ignores: [
    "webapp/thirdparty/**",
    "webapp/test/**"  // More aggressive ignores for CI
  ]
};

GitHub Actions:

- name: Lint (CI config)
  run: npm run lint -- --config .ui5lint.ci.config.js

Summary Checklist

Basic CI/CD (✅ Covered in templates):

  • Run linter on push/PR
  • Fail build on errors
  • Cache dependencies

Advanced Patterns:

  • Multi-platform testing
  • Coverage reporting
  • License checking
  • Dependency analysis
  • Security scanning
  • Artifact management
  • PR comments
  • Pre-commit hooks

Production-Ready:

  • Environment-specific configs
  • Monorepo support
  • Performance optimization (caching)
  • Historical tracking (artifacts)

Resources

UI5 Linter CI Workflow: https://github.com/UI5/linter/blob/main/.github/workflows/ci.yml

GitHub Actions Docs: https://docs.github.com/en/actions

GitLab CI Docs: https://docs.gitlab.com/ee/ci/

Jenkins Docs: https://www.jenkins.io/doc/


Document Version: 1.0 Last Verified: 2025-11-21 Next Review: 2026-02-21

Source: SKILL.md on GitHub

No alerts16d3 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill is a comprehensive documentation and template resource for integrating and using the SAPUI5/OpenUI5 Linter (@ui5/linter). It contains no executable scripts or malicious content and adheres to safe development practices.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

Signed by skilld at 620a19a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago
Other metadata
metadata
{
  "maintainer": "Eduard Jiglau",
  "maintainer_email": "hello@sap-ai-skills.com",
  "website": "https://sap-ai-skills.com",
  "version": "2.4.1",
  "last_verified": "2026-06-14",
  "ui5_linter_version": "1.22.0",
  "source": "https://github.com/UI5/linter",
  "documentation": "https://github.com/UI5/linter/blob/main/README.md",
  "keywords": [
    "SAPUI5",
    "OpenUI5",
    "UI5 Linter",
    "@ui5/linter",
    "static analysis",
    "deprecated APIs",
    "global variables",
    "CSP",
    "manifest.json",
    "ui5.yaml",
    "ESLint",
    "pre-commit hooks",
    "GitHub Actions",
    "CI/CD",
    "Node.js",
    "TypeScript",
    "XML",
    "JSON",
    "HTML",
    "YAML",
    "OData v2/v4",
    "async",
    "event handlers",
    "jQuery",
    "autofix",
    "performance optimization",
    "19 linting rules",
    "no-deprecated-api",
    "no-globals",
    "no-async-component-flags",
    "manifest-v2",
    "UI5 2.x migration"
  ]
}

README badge

README badge for secondsky/sap-skills/sapui5-linter