diff --git a/.github/workflows/test-deptrac.yml b/.github/workflows/test-deptrac.yml new file mode 100644 index 000000000000..0698809319fe --- /dev/null +++ b/.github/workflows/test-deptrac.yml @@ -0,0 +1,75 @@ +# When a PR is opened or a push is made, perform an +# architectural inspection on the code using Deptrac. +name: Deptrac + +on: + pull_request: + branches: + - 'develop' + - '4.*' + paths: + - 'app/**' + - 'system/**' + - 'composer.json' + - 'depfile.yaml' + - '.github/workflows/test-deptrac.yml' + push: + branches: + - 'develop' + - '4.*' + paths: + - 'app/**' + - 'system/**' + - 'composer.json' + - 'depfile.yaml' + - '.github/workflows/test-deptrac.yml' + +jobs: + build: + name: Architectural Inspection + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: composer, phive + extensions: intl, json, mbstring, gd, mysqlnd, xdebug, xml, sqlite3 + + - name: Validate composer.json + run: composer validate --strict + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Create composer cache directory + run: mkdir -p ${{ steps.composer-cache.outputs.dir }} + + - name: Cache composer dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create Deptrac cache directory + run: mkdir -p build/ + + - name: Cache Deptrac results + uses: actions/cache@v2 + with: + path: build + key: ${{ runner.os }}-deptrac-${{ github.sha }} + restore-keys: ${{ runner.os }}-deptrac- + + - name: Install dependencies + run: composer update --ansi --no-interaction + + - name: Run architectural inspection + run: | + sudo phive --no-progress install --global qossmic/deptrac --trust-gpg-keys B8F640134AB1782E + deptrac analyze --cache-file=build/deptrac.cache diff --git a/depfile.yaml b/depfile.yaml new file mode 100644 index 000000000000..c1d8b87c3db2 --- /dev/null +++ b/depfile.yaml @@ -0,0 +1,229 @@ +# Defines the layers for each framework +# component and their allowed interactions. +# The following components are exempt +# due to their global nature: +# - CLI & Commands +# - Config +# - Debug +# - Exception +# - Service +# - Validation\FormatRules +paths: + - ./app + - ./system +exclude_files: + - '#.*test.*#i' +layers: + - name: API + collectors: + - type: className + regex: ^Codeigniter\\API\\.* + - name: Cache + collectors: + - type: className + regex: ^Codeigniter\\Cache\\.* + - name: Controller + collectors: + - type: className + regex: ^CodeIgniter\\Controller$ + - name: Cookie + collectors: + - type: className + regex: ^Codeigniter\\Cookie\\.* + - name: Database + collectors: + - type: className + regex: ^Codeigniter\\Database\\.* + - name: Email + collectors: + - type: className + regex: ^Codeigniter\\Email\\.* + - name: Encryption + collectors: + - type: className + regex: ^Codeigniter\\Encryption\\.* + - name: Entity + collectors: + - type: className + regex: ^Codeigniter\\Entity\\.* + - name: Events + collectors: + - type: className + regex: ^Codeigniter\\Events\\.* + - name: Files + collectors: + - type: className + regex: ^Codeigniter\\Files\\.* + - name: Filters + collectors: + - type: bool + must: + - type: className + regex: ^Codeigniter\\Filters\\Filter.* + - name: Format + collectors: + - type: className + regex: ^Codeigniter\\Format\\.* + - name: Honeypot + collectors: + - type: className + regex: ^Codeigniter\\.*Honeypot.* # includes the Filter + - name: HTTP + collectors: + - type: bool + must: + - type: className + regex: ^Codeigniter\\HTTP\\.* + must_not: + - type: className + regex: (Exception|URI) + - name: I18n + collectors: + - type: className + regex: ^Codeigniter\\I18n\\.* + - name: Images + collectors: + - type: className + regex: ^Codeigniter\\Images\\.* + - name: Language + collectors: + - type: className + regex: ^Codeigniter\\Language\\.* + - name: Log + collectors: + - type: className + regex: ^Codeigniter\\Log\\.* + - name: Model + collectors: + - type: className + regex: ^Codeigniter\\.*Model$ + - name: Modules + collectors: + - type: className + regex: ^Codeigniter\\Modules\\.* + - name: Pager + collectors: + - type: className + regex: ^Codeigniter\\Pager\\.* + - name: Publisher + collectors: + - type: className + regex: ^Codeigniter\\Publisher\\.* + - name: RESTful + collectors: + - type: className + regex: ^Codeigniter\\RESTful\\.* + - name: Router + collectors: + - type: className + regex: ^Codeigniter\\Router\\.* + - name: Security + collectors: + - type: className + regex: ^Codeigniter\\Security\\.* + - name: Session + collectors: + - type: className + regex: ^Codeigniter\\Session\\.* + - name: Throttle + collectors: + - type: className + regex: ^Codeigniter\\Throttle\\.* + - name: Typography + collectors: + - type: className + regex: ^Codeigniter\\Typography\\.* + - name: URI + collectors: + - type: className + regex: ^CodeIgniter\\HTTP\\URI$ + - name: Validation + collectors: + - type: bool + must: + - type: className + regex: ^Codeigniter\\Validation\\.* + must_not: + - type: className + regex: ^Codeigniter\\Validation\\FormatRules$ + - name: View + collectors: + - type: className + regex: ^Codeigniter\\View\\.* +ruleset: + API: + - Format + - HTTP + Controller: + - HTTP + - Validation + Database: + - Entity + - Events + Email: + - Events + Entity: + - I18n + Filters: + - HTTP + Honeypot: + - Filters + - HTTP + HTTP: + - Cookie + - Files + - URI + Images: + - Files + Model: + - Database + - I18n + - Pager + - Validation + Pager: + - URI + - View + Publisher: + - Files + - URI + RESTful: + - +API + - +Controller + Router: + - HTTP + Security: + - Cookie + - HTTP + Session: + - Cookie + - Database + Throttle: + - Cache + Validation: + - HTTP + View: + - Cache +skip_violations: + # Individual class exemptions + CodeIgniter\Entity\Cast\URICast: + - CodeIgniter\HTTP\URI + CodeIgniter\Log\Handlers\ChromeLoggerHandler: + - CodeIgniter\HTTP\ResponseInterface + CodeIgniter\View\Table: + - CodeIgniter\Database\BaseResult + CodeIgniter\View\Plugins: + - CodeIgniter\HTTP\URI + + # BC changes that should be fixed + CodeIgniter\HTTP\ResponseTrait: + - CodeIgniter\Pager\PagerInterface + CodeIgniter\HTTP\ResponseInterface: + - CodeIgniter\Pager\PagerInterface + CodeIgniter\HTTP\Response: + - CodeIgniter\Pager\PagerInterface + CodeIgniter\HTTP\RedirectResponse: + - CodeIgniter\Pager\PagerInterface + CodeIgniter\HTTP\DownloadResponse: + - CodeIgniter\Pager\PagerInterface + CodeIgniter\Validation\Validation: + - CodeIgniter\View\RendererInterface