Coder Social home page Coder Social logo

laminas / laminas-ci-matrix-action Goto Github PK

View Code? Open in Web Editor NEW
23.0 17.0 15.0 1.41 MB

GitHub Action for creating a CI job matrix.

License: BSD 3-Clause "New" or "Revised" License

Dockerfile 1.89% Shell 4.36% TypeScript 93.73% PHP 0.02%
continuous-integration

laminas-ci-matrix-action's Introduction

Create a CI matrix for use in a GitHub Action

🇷🇺 Русским гражданам

Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.

У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.

Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"

🇺🇸 To Citizens of Russia

We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.

One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.

You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"

This repository represents a GitHub action that allows you to introspect a PHP project in order to build up a test matrix which can later be run by the laminas/laminas-continuous-integration-action.

It identifies jobs to run based on presence or absence of configuration files in the package. Currently, it identifies the following:

  • PHP versions to run unit tests against based on the php constraint in the composer.json file.
  • Whether to run against a "locked" set of dependencies based on the presence of a composer.lock file.
  • PHPUnit tests based on the presence of phpunit.xml.dist or phpunit.xml files.
  • phpcs checks based on the presence of phpcs.xml.dist or phpcs.xml files.
  • Psalm checks based on the presence of psalm.xml.dist or psalm.xml files.
  • ComposerRequireChecker checks based on the presence of composer-require-checker.json file.
  • phpbench benchmarks based on the presence of a phpbench.json.
  • Infection mutation tests based on the presence of infection.json or infection.json.dist. In case that roave/infection-static-analysis-plugin is installed, this will be used instead.
  • Markdown documentation based on the presence of a mkdocs.yml and/or markdown files in the doc/book/ or doc/books/ trees.
  • Codeception checks based on the presence of codeception.yml.dist or codeception.yml files.

Further, when triggered by a pull_request event, it determines what checks are necessary based on which files were affected.

Usage

jobs:
  matrix:
    name: Generate job matrix
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.matrix.outputs.matrix }}
    steps:
      - name: Gather CI configuration
        id: matrix
        uses: laminas/laminas-ci-matrix-action@v1

  qa:
    name: QA Checks
    needs: [matrix]
    runs-on: ${{ matrix.operatingSystem }}
    strategy:
      fail-fast: false
      matrix: ${{ fromJSON(needs.matrix.outputs.matrix) }}
    steps:
      - name: ${{ matrix.name }}
        uses: laminas/laminas-continuous-integration-action@v1
        with:
          job: ${{ matrix.job }}

Generally, you will use this as a dependency of a job that uses laminas/laminas-continuous-integration-action, as demonstrated in the above configuration.

actions/checkout not required

An actions/checkout step prior to this action is not required, as it will perform a checkout into the WORKDIR on its own if none has been performed previously. We recommend using actions/checkout only if you need to access QA artifacts in a later step.

Outputs

It spits out a single output, "matrix", which is a JSON string in the following format:

{
  "include": [
    {
      "name": "(string) Name of the check being run",
      "operatingSystem": "(string) Name of the OS the job should be run on (generally ubuntu-latest)",
      "action": "(string) GHA to run the step on; currently ignored, as GHA does not support dynamic action selection",
      "job": "(string) JSON object detailing the job (more on this later)"
    }
  ],
  "exclude": [
    {
    }
  ]
}

The "exclude" element will only be present if the package using the action provides it via configuration. Each item in the "exclude" array will be an object, with one or more of the keys listed in the "include" objects; when a job matches all elements specified in the "exclude" array, it will be excluded from runs.

The "job" element is a string JSON object detailing the job to run. Note: it is not an object; it is a JSON string but it MUST have the structure as shown here.

Job Element

The "job" element will have the following elements, but is not restricted to them:

{
  "php": "(optional) string PHP minor version to run against; @lowest and @latest aliases point to the minimum and maximum PHP versions which are supported by the project",
  "extensions": [
    "(optional) extension names to install; names are from the ondrej PHP repository, minus the php{VERSION}- prefix"
  ],
  "ini": [
    "(optional) php.ini directives, one per element; e.g. 'memory_limit=-1'"
  ],
  "dependencies": "(optional) dependencies to test against; one of lowest, locked, latest. default: locked",
  "command": "(required) command to run to perform the check", 
  "ignore_platform_reqs_8": "(optional; deprecated) boolean; whether to add `--ignore-platform-req=php` to Composer for PHP 8.0. default: true",
  "ignore_php_platform_requirement": "(optional) boolean; whether to add `--ignore-platform-req=php` to Composer for this job.",
  "additional_composer_arguments": [
      "(optional) list of arguments to be passed to `composer install` and `composer update`"
  ]
}

Configuration

The package can include a configuration file in its root, .laminas-ci.json, which can provide the following:

{
  "extensions": [
    "extension names to install"
  ],
  "ini": [
    "php.ini directives"
  ],
  "checks": [
    {
    }
  ],
  "additional_checks": [
    {
    }
  ],
  "exclude": [
    {
    }
  ],
  "ignore_php_platform_requirements": {
      "8.0": true
  },
  "stablePHP": "8.0",
  "additional_composer_arguments": [
  ]
}

Providing specific checks to run

If you do not want to autodiscover checks to run, you can provide the "checks" configuration. Each element in that array should be in the same format as listed above for the outputs:

{
  "name": "(string) Name of the check being run",
  "operatingSystem": "(string) Name of the OS the job should be run on (generally ubuntu-latest)",
  "action": "(string) GHA to run the step on; currently ignored, as GHA does not support dynamic action selection",
  "job": "(object|string) JSON object detailing the job"
}

The "job" element can either be a JSON string representing a job, or an object. In each case, it MUST have the structure as shown here but the "php" element is mandatory in here and MUST contain the minor PHP version to run the check against.

The action validates each check and its job to ensure it is structured correctly, and will provide warnings if not, omitting any check that is malformed from the output.

If the checks element is populated, the matrix will not include any auto-detected checks, and will only output the jobs listed in that element.

Providing additional checks

The additional_checks key allows package authors to provide checks to run in addition to any discovered. This allows providing checks for tools the matrix discovery tools do not know about, or providing one-off checks (such as benchmarks or mutation tests).

The syntax for the additional_checks key is as follows:

{
    "additional_checks": [
        {
            "name": "(string; REQUIRED) name of the check to run",
            "job": "(object) JSON object detailing the job"
        }
    ]
}

A job per PHP version per dependency set will be created, and the "name" will be appended with "on PHP {VERSION} with {DEPS} dependencies" during an actual run. The "job" element MUST have the structure as shown here but the "php" element is mandatory in here and MUST contain either the minor PHP version to run the check against or a wildcard * to run the against all supported PHP versions. You can pass the wildcard, "*", for the "php" element; when you do, the ignore_php_platform_requirement element will be ignored. It is possible to provide per-version flags by adding the ignore_php_platform_requirements element instead.

The tool discovers checks first, then appends any additional_checks are concatenated, and then any exclude rules are applied.

Excluding specific jobs

You can exclude specific jobs by using their names:

{
  "exclude": [
    {
      "name": "PHPUnit"
    }
  ]
}

If you want to limit the exclusion to specific PHP versions, you can additionally add a PHP version:

{
   "exclude": [
      {
         "name": "PHPUnit",
         "php": "8.0"
      }
   ]
}

In case you only want to exclude jobs for specific Composer dependency sets, add dependencies to the exclude configuration:

{
   "exclude": [
      {
         "name": "PHPUnit",
         "php": "8.0",
         "dependencies": "latest"
      }
   ]
}

Testing matrix generation locally using Docker

To test matrix generation in a local checkout on your own machine, you can do the following:

$ docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-ci-matrix:1

This will run the action locally and detail what matrix will be produced; it can be particularly useful for debugging issues with your .laminas-ci.json configuration.

Development

In case you want to contribute features, bugfixes, tests or JSONSchema enhancements, you might want to build the docker container locally.

To do so, you can follow these steps:

  1. Build the docker container by executing $ docker build -t laminas/laminas-ci-matrix-action:dev-local .
  2. Change to the tests/ directory you want to create a matrix for
  3. Run the docker container while overriding the entrypoint.sh to ensure the diff is being passed to the matrix generator
    • docker run -it --entrypoint "/action/main.js" -v $(realpath .):/github/workspace -w=/github/workspace docker.io/laminas/laminas-ci-matrix-action:dev-local $(test -r diff && cat diff || echo "")

laminas-ci-matrix-action's People

Contributors

basz avatar boesing avatar fahl-design avatar ghostwriter avatar gsteel avatar mauriciofauth avatar michalbundyra avatar ocramius avatar renovate[bot] avatar weierophinney avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laminas-ci-matrix-action's Issues

Initial clone not working for private repositories

Bug Report

Q A
Version(s) 1.17

Summary

Initial git clone fails for private repositories

Current behavior

Run laminas/laminas-ci-matrix-action@v1
/usr/bin/docker run --name ghcriolaminaslaminascimatrix1_c6d[2](https://github.com/plhw/lab-api-model-valueobject/runs/8200006290?check_suite_focus=true#step:3:3)87 --label 786a9b --workdir /github/workspace --rm -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/lab-api-model-valueobject/lab-api-model-valueobject":"/github/workspace" ghcr.io/laminas/laminas-ci-matrix:1
Cloning into '.'...
Cloning repository
fatal: could not read Username for 'https://github.com/': No such device or address

How to reproduce

  1. create a private repository on github
  2. add this workflow https://github.com/laminas/workflow-continuous-integration
  3. Add GITHUB_TOKEN as environment variable to the steps
  4. push

Expected behavior

Initial checkout succeeds

Notes

Shouldn't the auth token be persisted to the local git config before it can be used by git commands? actions/checkout action seems to do that (See the Readme).

Documentation: Add list of supported tools and how to ensure the checks are being properly generated

Feature Request

Q A
New Feature no
RFC no
BC Break no

Summary

This component supports some tools for CI pipeline, such as:

  • PHPCodeSniffer
  • Psalm
  • PHPUnit
  • PHP-CS-Fixer
  • etc.

(List of supported tools can be found in this file)

At least for one tool (PHP-CS-Fixer), we require a project to have a composer-require-checker.json configuration file available. This is because the tool does not have a default filename for this and thus, we decided to go with this filename.

For infection, we do support the static-analysis tool from Roave as well, but do not list it anywhere in the README or docs.

So this Issue is to ensure we do improve the documentation of this github action so that every1 who wants to use this CI Pipeline is aware of how to configure the project.

Missing `backwardCompatibilityCheck` configuration flag documentation

Summary

Flag was introduced with 1.23.0 but I actually missed to properly add it to the documentation (README.md) though it is part of the configuration schema:

"backwardCompatibilityCheck": {
"type": "boolean",
"title": "Flag to enable/disable backwards compatibility check",
"description": "This flag enables/disables backwards compatibility check using roave/backward-compatibility-check.",
"default": false
},

Switching to shivammathur/php-builder

RFC

Q A
Proposed Version(s) any next minor
BC Break? I think not

Goal

I think it would be quite helpful to use shivammathur/php-builder to early create issues and PRs to add support for PHP 8.1 so we do not have the same mess as with PHP 8.0 which is still not yet finished (no blaming, we are just lacking contributions - thats all).

Background

Due to the usage of usage of https://github.com/oerdnj/deb.sury.org, we are currently limited to the versions Ondřej supports.
For PHP 8.0, he requested funding to make it available (oerdnj/deb.sury.org#1439 (comment), no blaming) and in the end, PHP 8.0 was installable (thankfully to laravel and/or seravo) around 2020-10-05.

https://github.com/shivammathur/php-builder on the other end had PHP 8.0 available around december 2019.

Having PHP 8.1 available in October or later within sury repository (he states that he always waits for a first beta RC), we will lack a bunch of months to catch up until november.

Considerations

The impact on users would be nearly none as the PHP versions are just consumed and build from the same source. Thus, for the enduser, nothing will change.

Proposal(s)

Users will consume the docker images as before.

Appendix

Instead of pre-building Ondřej PHP to our docker images, we should use Shivam's php-builder instead so we can probably start creating branches which support PHP 8.1 as of now.

I am not sure if its possible to setup cron-like workflow triggers based on Open PRs which might be flagged by a specific label?
Probably, creating a dedicated label for early-php-support will always execute PRs automatically once a month until merged?

Any feedback is welcome.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

dockerfile
Dockerfile
  • node 21.7.3-alpine
  • node 21.7.3-alpine
github-actions
.github/workflows/build-and-push-containers.yml
  • actions/checkout v4
  • docker/setup-qemu-action v3
  • docker/setup-buildx-action v3
  • docker/login-action v3
  • docker/build-push-action v5
.github/workflows/continuous-integration.yml
  • actions/checkout v4
  • actions/checkout v4
  • docker/setup-qemu-action v3
  • docker/setup-buildx-action v3
  • docker/build-push-action v5
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/download-artifact v4
  • sergeysova/jq-action v2
  • sergeysova/jq-action v2
  • actions/checkout v4
  • docker/setup-qemu-action v3
  • docker/setup-buildx-action v3
  • docker/build-push-action v5
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
.github/workflows/create-additional-action-tags.yml
  • actions/checkout v4
.github/workflows/release-on-milestone-closed.yml
  • actions/checkout v4
  • laminas/automatic-releases v1
  • laminas/automatic-releases v1
  • laminas/automatic-releases v1
  • laminas/automatic-releases v1
  • laminas/automatic-releases v1
npm
package.json
  • @actions/core ^1.10.0
  • @cfworker/json-schema ^1.12.5
  • @types/semver ^7.3.13
  • semver ^7.3.8
  • @types/jest ^29.2.0
  • @types/node ^20.0.0
  • @types/webpack ^5.28.0
  • @typescript-eslint/eslint-plugin ^5.41.0
  • @typescript-eslint/parser ^5.41.0
  • dotenv ^16.3.1
  • eslint ^8.26.0
  • eslint-config-incredible ^2.4.2
  • eslint-import-resolver-typescript ^3.5.2
  • eslint-plugin-import ^2.26.0
  • eslint-plugin-node ^11.1.0
  • jest ^29.2.2
  • source-map-loader ^5.0.0
  • ts-jest ^29.0.3
  • ts-node ^10.9.1
  • typescript ~5.4.0
  • webpack ^5.74.0
  • webpack-cli ^5.0.0
  • npm ^10.0.0
  • node ^21.7.0

  • Check this box to trigger a request for Renovate to run again on this repository

Allow org-wide configuration

Feature Request

Q A
New Feature yes
BC Break no

Summary

It might be handy to have org-wide configuration available for CI stuff. Renovate for examples allows config merging with organization config:

https://github.com/laminas/.github/blob/main/renovate-config.json
https://github.com/laminas/laminas-servicemanager/blob/c97780e74ac5c2fdf2aa4876bccdc718b6fc6ed9/renovate.json#L4

The idea of this feature request is to allow .laminas-ci.json files being available in the .github repository as well.
Once it is available, its being merged.
It should not be dependend on a config entry (as most projects do not even have .laminas-ci.json in-place.
So I'd always check the organization for having a .laminas-ci.json and if so, that is used as a default and then merges explicit configuration with the project file (if available).

Add composer.json linting to every matrix

Feature Request

Q A
New Feature yes
RFC no
BC Break no

Summary

Hi, I'd like to add to every matrix one with the purpose of linting composer.json. In Paratest we use 4 steps:

Command Reference
composer validate --strict https://getcomposer.org/doc/03-cli.md#validate
composer-normalize --dry-run https://github.com/ergebnis/composer-normalize
composer-require-checker check https://github.com/maglnet/ComposerRequireChecker
composer-unused https://github.com/composer-unused/composer-unused

Composer `php` constraints with `,` are not supported

Bug Report

Q A
Version(s) 1.11.5

Summary

When a component uses a more complex constraint which contains ,, the matrix is not able to infer supported PHP versions anymore.

Current behavior

Supported PHP versions are not detected at all.

How to reproduce

composer.json

{
    "require": {
        "php": ">=5.6,<=8.1.99"
    }
}

Expected behavior

All versions between PHP 5.6 and 8.1.99 are detected. As of writing this issue, this would be:

  • 5.6
  • 7.0
  • 7.1
  • 7.2
  • 7.3
  • 7.4
  • 8.0
  • 8.1

Missing jobs due to incompatibility composer PHP version parser

Bug Report

Q A
Version(s) <=1.11.4

Summary

the semver version parser does not work correctly if composer.json uses this format "php": ">=7.4, <8.2", which prevents certain jobs from being created.

function gatherVersions(composerJson) {
if (JSON.stringify(composerJson) === '{}') {
return [];
}
let versions = [];
INSTALLABLE_VERSIONS.forEach(function (version) {
if (semver.satisfies(version + '.0', composerJson['require']['php'])) {
versions.push(version);
}
});
return versions;
}

Current behavior

How to reproduce

setup a repo with a composer.json file with "require": {"php": ">=7.4, <8.2"} .

Expected behavior

Generate jobs for PHPUnit on PHP 7.4, 8.0, & 8.1

Implement dependency injection

This component does not really use OOP in most places and thus, providing logging and stuff is quite complicated.

To solve this, we can implement a dependency injection library.

I do quote the answer from @internalsystemerror here as he provided some information on how we could move over to dependency injection.


I'm mostly familiar with the DI in Angular, but there are (smaller) libraries available e.g. TypeDI or even TSyringe by MS

Originally posted by @internalsystemerror in #119 (comment)

Detect required PHP extensions from locked dependencies

Feature Request

Q A
New Feature yes
BC Break no

Summary

In #58, we introduced the extension detection from composer.json.
However, I've seen a comment in #80 where a project had to add an extension to its .laminas-ci.json because it is required by a 3rd-party dependency.

I was thinking about that and I came to the conclusion, that it might be possible to iterate through the composer.lock packages to actually detect all PHP extensions from the require section of their composer.json.

JSON Schema for `.laminas-ci.json`

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

This action is currently parsing project configurations and ignores badly formatted jobs while adding a warning to the output.

I would prefer having a check fail. This could be done by creating a JSON Schema along with a Schema validation as done for composer.json (as of 1.8.0).

WDYT?


We could also add a JSON schema to the container action and re-use it in here for output validation (as part of CI of this container).

Consider composer validation commands

Feature Request

Q A
New Feature yes
RFC yes
BC Break yes/no maybe?

Summary

  1. Run composer validate to confirm that there are no issues with the composer.json file.
  2. Run composer check-platform-reqs, at least where --ignore-platform-reqs is not used in order to confirm that the installed packages should function correctly.
  3. Run composer audit to get a list of the vulnerable packages (if any) as the warning on install just lists the number of vulnerable packages, not what they are https://github.com/laminas/laminas-cli/runs/8005445567?check_suite_focus=true#step:3:315

Run psalm against highest PHP version?

Feature Request

Q A
New Feature yes
RFC sort of
BC Break not sure

Summary

While working on laminas/laminas-hydrator#95 I had to completely exclude my new code in psalm.xml, since the component supports PHP 8.0 but the code uses a PHP8.1 feature (enums). I think it would make sense to run Psalm on the highest stable PHP version so new features can be covered.

Simplify `.laminas-ci.json`

Feature Request

Q A
New Feature yes
RFC yes
BC Break yes

Summary

The .laminas-ci.json allows to pass checks which overrides the additional_checks and thus are mutually exclusive. This makes the JSON schema more bloated as we have to provide two configuration combinations with either checks or additional_checks.

The .checks[].job element has is allowed to be a string which also makes it more error-prone.
It also states that it is possible to select an additional "action" which can be used with the CI matrix which is actually not really true as if someone choses another "action", that action also have to parse the job JSON-string and from this perspective, I dont really see the benefit of having checks.

Due to the fact that .checks[].job is a string, it also cannot be validated by the JSON schema which is feature-requested in #49.

Is there any project around which uses the .checks functionality from .laminas-ci.json? If not, I would prefer getting rid of that to simplify the matrix action.

Fix broken v1 tag

Bug Report

The laminas/laminas-continuous-integration action was incorrectly specifying laminas-ci-matrix as its tag prefix, which led to it overwriting the v1 tag for this action.

We simply need to force a new release.

Optimize `diff` within CI pipeline output for better readability in case of failing tests

Feature Request

Q A
New Feature yes

Summary

In #62, a CI pipeline was created for this action.
Sadly, the output of the integration tests diff are not that easy to understand.

I was thinking of using something like https://github.com/josephburnett/jd

Another "problem" is, that every check has a job property which contains the job as a stringified JSON.
Maybe this might be also fixed with using jd and maybe with a colorized output (not sure if thats even possible for GHA) but if not, using diff to actually do the diff might suffice while using jd to display some kind of "pretty printed JSON".

Missing support for `psalm/phar`

Bug Report

Q A
Version(s) 1.39.0

Summary

When Psalm is installed using psalm/phar instead of vimeo/psalm, an error occurs because vendor/vimeo/psalm/config.xsd does not exist.

refs #31, psalm/phar#5

Current behavior

Running before_script: xmllint --schema vendor/vimeo/psalm/config.xsd psalm.xml
warning: failed to load external entity "vendor/vimeo/psalm/config.xsd"
<?xml version="1.0"?>
Schemas parser error : Failed to locate the main schema resource at 'vendor/vimeo/psalm/config.xsd'.
WXS schema vendor/vimeo/psalm/config.xsd failed to compile
<psalm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" errorLevel="1" resolveFromConfigFile="true" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" errorBaseline="psalm-baseline.xml" findUnusedBaselineEntry="true" findUnusedCode="false">
    <projectFiles>
        <directory name="src"/>
        <ignoreFiles>
            <directory name="vendor"/>
        </ignoreFiles>
    </projectFiles>
</psalm>

How to reproduce

In a project where psalm.xml exists, replacing vimeo/psalm with psalm/phar will reproduce the problem.

michaelpetri/phpunit-consecutive-arguments#109

Expected behavior

No errors.

support for the config.bin-dir options in composer.json

Feature Request

Q A
New Feature yes
BC Break no

Summary

Tools binaries might be in a different location than /vendor/bin.

We could a support for the config.bin-dir options in composer.json

This outputs the current set location.

composer config 'bin-dir'

[RFC]: stop testing `latest` dependencies

RFC

While running tests over the last few days, I noticed that we have test failure due to runtime depreciations (which I still firmly believe to be an abomination) when running latest dependencies against the lowest supported PHP version of a repository.

We have to consider 2 problems in this test matrix entry:

  1. lowest PHP version will hardly ever receive latest dependencies anyway
  2. we refresh the composer.lock of all repositories on a nightly basis, therefore detecting upstream breakages

Given that updating lock files is equivalent to testing latest dependencies, I therefore suggest dropping the latest entries from our generated CI matrix.

Q A
Proposed Version(s) 2.0.0
BC Break? Yes

Note: I counted this as BC break, because it changes assumptions around testing depth

Enable code checks or linters when files from tools are changed (i.e. run all PHPUnit checks when `phpunit.xml.dist` is the only file within the diff)

Feature Request

Q A
New Feature yes

Summary

Currently, if the diff only contains a change for phpunit.xml.dist or infection.json (etc.), no checks would be generated.
With #83 it would be quite easy to enable specific tool checks for the diff.

Maybe this issue should be renamed to "only enable checks for tools which do match the diff (if a diff is available)". For now, this Ticket is just to keep track of ideas which came up during the development of #83.

`.laminas-ci.json` change in PR does not execute all jobs

Bug Report

Q A
Version(s) 1.10.0

Summary

When adding .laminas-ci.json or when changing that file, I would expect that the matrix generates all jobs as:

  1. there could be new jobs added with additional_checks
  2. existing jobs are being excluded using exclude
  3. existing jobs are being overridden with checks

boesing/psalm-plugin-stringf#15
https://github.com/boesing/psalm-plugin-stringf/actions/runs/1226396745

Current behavior

No checks are generated.

How to reproduce

Create a PR with only changes applied to .laminas-ci.json

Expected behavior

The matrix would create the same changes as done in non-PRs.

Add in `composer-require-checker` as a globally installed tool

Feature Request

Q A
New Feature yes
RFC no
BC Break no

Summary

composer-require-checker is a useful tool for ensuring that composer.json contains all the necessary required packages. It is advised to be used as a standalone tool, or as globally installed, not as a development dependency.

Ideally this should be installed into this action as a PHP tool, however this is dependent on the resolution of #119.

Enable `backwardsCompatibilityCheck` by-default for laminas components

Feature Request

Q A
New Feature yes
BC Break only for laminas-specific projects which is on-purpose

Summary

Add a check to the configuration reading for laminas/*, mezzio/* and laminas-api-tools/* components regarding the backwardsCompatibilityCheck flag.
If that flag is not explicitly set to false in project configuration files, we want to enable it for packages of the orgs mentioned above.

Bump `package.json` to use `node:^19`

Bug Report

As found in #134, we use node:^18 in package.json and node:19 in Dockerfile.

Q A
Version(s) 1.19.0

NPM happily keeps installing everything with a warning:

 #13 1.580 npm WARN EBADENGINE Unsupported engine {
#13 1.581 npm WARN EBADENGINE   package: undefined,
#13 1.581 npm WARN EBADENGINE   required: { node: '^18' },
#13 1.581 npm WARN EBADENGINE   current: { node: 'v19.0.0', npm: '8.19.2' }
#13 1.582 npm WARN EBADENGINE }

That's why I kept going and released 1.19.0 anyway: for 1.20.0 we should fix the dependency range.

Marking extensions as optional

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

It would be great to have a way to mark extensions as optional, to be able to test with the extensions and without the extensions.
This way is possible to test if the code works correctly when the optional extension is not installed.

Maybe a new configuration key like optional_extensions.

Allow `php` and `dependency` in `exclude` along with `name` reflecting the tools/checks name

Feature Request

Q A
New Feature yes
BC Break no

Summary

Currently, one has to create plenty of exclude for PHPUnit for example.
Given the fact, that PHPUnit is executed in at least lowest and latest (and also locked for minimum supported PHP version), that would mean at least 3 entries within exclude to exclude a specific PHP version with all dependencies.

I'd like to suggest something like this (on top of the current way of excluding checks):

{
     "exclude": [
        {
             "name": "PHPUnit",
             "php": "8.0",
             "dependencies": "*",
        }
    ]
}

This would exclude all PHPUnit runs on PHP 8.0 with all composer dependencies.

Code Coverage Reporters

Feature Request

Q A
New Feature yes
RFC ?
BC Break ?

Summary

It would be really cool to detect or configure the ability to report coverage after successful PHPUnit actions. I guess these would be vendor specific?

Most laminas repos seem to use coveralls and have an existing coveralls.yml file. I personally tend to favour codecov which can use a config file but doesn't require one.

Is this a feature that you might consider?

Empty or non-existent `ignore_php_platform_requirements` does not disable PHP 8.0 default behavior

Bug Report

Q A
Version(s) 1.11.5

Summary

When I've impelemented the ignore_php_platform_requirements feature, the main idea was to get rid of the old and yet deprecated ignore_platform_reqs_8 feature, which defaulted to true.

I was assuming (and thought I've implemented it that way 😅) that when adding an empty ignore_php_platform_requirements object to the .laminas-ci.json, we do not explicitly mark PHP 8.0 as true.
Sadly, it does and thus, I'd like to either change this and/or remove ignore_platform_reqs_8 entirely.

ignore_php_platform_requirements option is available since v1.9.0 (released in 08/2021)

Current behavior

Adding an empty ignore_php_platform_requirements does not prevent ignoring platform reqs for PHP 8.0.

How to reproduce

Add an empty ignore_php_platform_requirements to the .laminas-ci.json in a project with PHP 8.0 support and check matrix output. It contains ignore_php_platform_requirement: true for PHP 8.0.

Expected behavior

ignore_php_platform_requirement should be false for PHP 8.0.

Provide ability to specify jobs defined in checks configuration as objects

Feature Request

Q A
New Feature yes
BC Break no

Summary

Currently, the "checks" element is expected to be an object with the following schema:

{
  "name": "(string) Name of the check being run",
  "operatingSystem": "(string) Name of the OS the job should be run on (generally ubuntu-latest)",
  "action": "(string) GHA to run the step on; currently ignored",
  "job": "(string) JSON object detailing the job"
}

For configuration purposes, it would be easier if the "job" element of a check could be an actual JSON object:

{
  "name": "...",
  "operatingSystem": "..."
  "action": "..."
  "job": {
    "php": "php version",
    "extensions": [],
    "ini": [],
    "dependencies": "...",
    "command": "..."
  }
}

Each of "extensions", "ini", and "dependencies" are technically optional, but SHOULD be provided; I'd suggest we raise a notice of some sort in the action if they are missing.

For BC purposes, we should allow either a JSON string OR an object.

GHA `set-output` is deprecated

It seems that the way how we (I) implemented the tests in this project might become invalid at some point in time.
I've recently seen the output of one of the tests within a PR and it says:

Warning: The set-output command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/

I just create this ticket as a reminder that there is a TODO but unfortunately I don't have time as of right now to work on this right now.

`ext-pdo_sqlite` is not really installable

Bug Report

Q A
Version(s) 1.13.0

Summary

Given following composer.json:

{
    "require": {
        "php": "~8.1.0",
        "ext-pdo_sqlite": "*"
    }
}

CI fails with:


Run laminas/laminas-continuous-integration-action@v1
/usr/bin/docker run --name ghcriolaminaslaminascontinuousintegration1_e9f03a --label 94859b --workdir /github/workspace --rm -e INPUT_JOB -e HOME -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL -e GITHUB_REF_NAME -e GITHUB_REF_PROTECTED -e GITHUB_REF_TYPE -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e GITHUB_STEP_SUMMARY -e RUNNER_OS -e RUNNER_ARCH -e RUNNER_NAME -e RUNNER_TOOL_CACHE -e RUNNER_TEMP -e RUNNER_WORKSPACE -e ACTIONS_RUNTIME_URL -e ACTIONS_RUNTIME_TOKEN -e ACTIONS_CACHE_URL -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/event-sourcing-workshop/event-sourcing-workshop":"/github/workspace" ghcr.io/laminas/laminas-continuous-integration:1  "{\"command\":\"./vendor/bin/phpcs -q --report=checkstyle | cs2pr\",\"php\":\"8.1\",\"extensions\":[\"pdo_sqlite\",\"sqlite3\"],\"ini\":[],\"dependencies\":\"locked\",\"ignore_platform_reqs_8\":false,\"ignore_php_platform_requirement\":false,\"additional_composer_arguments\":[]}"
Received job: {"command":"./vendor/bin/phpcs -q --report=checkstyle | cs2pr","php":"8.1","extensions":["pdo_sqlite","sqlite3"],"ini":[],"dependencies":"locked","ignore_platform_reqs_8":false,"ignore_php_platform_requirement":false,"additional_composer_arguments":[]}
Marking PHP 8.1 as configured default
Cloning repository
Cloning into '.'...
Checking out ref feature/working-prototype
Switched to a new branch 'feature/working-prototype'
Branch 'feature/working-prototype' set up to track remote branch 'feature/working-prototype' from 'origin'.
Installing packaged extensions: php8.1-pdo_sqlite php8.1-sqlite3 

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Get:1 https://packages.microsoft.com/ubuntu/20.04/prod focal InRelease [10.5 kB]
Get:2 http://ppa.launchpad.net/ondrej/php/ubuntu focal InRelease [23.9 kB]
Get:3 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Hit:4 http://archive.ubuntu.com/ubuntu focal InRelease
Get:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:6 https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages [203 kB]
Get:7 http://archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Get:8 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 Packages [175 kB]
Get:9 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [2087 kB]
Get:10 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [2542 kB]
Get:11 http://archive.ubuntu.com/ubuntu focal-updates/restricted amd64 Packages [1571 kB]
Get:12 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [1176 kB]
Get:13 http://security.ubuntu.com/ubuntu focal-security/universe amd64 Packages [888 kB]
Fetched 9012 kB in 3s (2992 kB/s)
Reading package lists...
Building dependency tree...
Reading state information...
30 packages can be upgraded. Run 'apt list --upgradable' to see them.

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package php8.1-pdo_sqlite

This is obviously an edge case, but even specifying extensions in .laminas-ci.json doesn't help, as the default behavior still stays active

Use `composer/semver` internally to verify PHP version compatibility

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

As of now, we are using some semver javascript library. Since that actually does not align with all the "features" of composer, we might want to create a little PHAR which uses composer/semver under the hood to simply exit with 0 if PHP version is supported by the constraint or 1 if not.

Adding some kind of child_process to our matrix javascript node binary and we can run that PHAR from within JS for a more accurate version detection.

This would also fix #86

Thoughts?

Include `roave/backward-compatibility-check` in CI runs

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

https://github.com/Roave/BackwardCompatibilityCheck helps in guaranteeing that no accidental BC breaks land in existing code in minor/patch releases.

My suggestion is to add a CI action that:

This could be a bit trickier than usual, because:

  • we need to git fetch the latest release, as well as HEAD
  • we need to make sure we're comparing HEAD against the correct release: depends on the target branch of a pull request

Add the ability to specify additional checks to perform

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

Currently, the .laminas-ci.json file allows you to specify a "checks" key, which is an array of checks to run. When defined, it specifies your entire matrix to run; the action does no discovery of its own at that point.

Sometimes, however, you may only want to add one or more checks to perform in addition to any that were discovered. As an example, this could solve the problem presented in #4, which requests the ability to run code coverage reports, or a scenario where you want to run an integration test suite that's normally excluded from your unit tests.

My proposal is to allow the following additions to the .laminas-ci.json format:

{
    "additional_checks": [
        {}
    ]
}

where each object in the additional_checks array has the following format (same format as individual items in the matrix):

{
      "name": "(string) Name of the check being run",
      "operatingSystem": "(string) Name of the OS the job should be run on (generally ubuntu-latest)",
      "action": "(string) GHA to run the step on; currently ignored, as GHA does not support dynamic action selection",
      "job": "(string) JSON object detailing the job"
}

Only "name" and "job" would be required; the other items could use defaults.

The "job" would then follow the same format as jobs currently do:

{
  "php": "string PHP minor version to run against",
  "extensions": [
    "extension names to install; names are from the ondrej PHP repository, minus the php{VERSION}- prefix",
  ],
  "ini": [
    "php.ini directives, one per element; e.g. 'memory_limit=-1'",
  ],
  "dependencies": "dependencies to test against; one of lowest, locked, latest",
  "command": "command to run to perform the check",
}

with the following rules:

  • "php" would be optional; if not provided, the assumption would be to use the "stable-php" version
    • Nice to have: "*" to mean run against all versions; the check gets cloned, with each version using a different PHP version
  • "extensions" is optional; if not provided, an empty array will be used
  • "ini" is optional; if not provided, an empty array will be used
  • "dependencies" is optional; if not provided, the assumption is to use "locked"
    • Nice to have: "*" to mean run against each of latest, locked, and lowest
    • Nice to have: allow an array of values; if an array is present, one job is created per PHP version
  • "command" is required

This would give consumers more flexibility in defining one-off checks, or to run checks that we do not yet have the ability to detect in the container.

Implement a mechanism to shrink the `vimeo/psalm` baseline, when possible

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

Whenever we make small adjustments to our codebase, we may improve type information.

It may be a good idea to reduce our psalm-baseline.xml accordingly, when possible.

The rough idea is that:

  1. a new change is pushed to the main configured branch (to be detected by CI)
  2. the change removed one type error somewhere
  3. we run vendor/bin/psalm --update-baseline, which should reduce the contents of psalm-baseline.xml (if it exists)
  4. if changes are produced by this pipeline, commit them
  5. push these changes to a reserved branch
  6. run CI on that branch
  7. auto-merge to main branch

This is extremely elaborate, compared to our current CI tasks, so it requires a lot of added engineering work around the pipeline, but it can probably be done :-)

Verify `composer.json` constraint changes

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

We do have a few components where we actually implement specific interfaces, such as PSR ones.
We had a release for laminas-servicemanager which stated to support psr/container v2 support. That was incorrect, due to several things:

  1. the composer.json did not provide support for ^2.0 of the psr/container package via psr/container-implementation.
  2. the composer.lock did not contain the latest version of psr/container since it got blocked by a 3rd-party library which did not supported psr/container v2 yet (but was only added as a dev-dependency)

At least due to the 2nd issue, all tests were passing and thus the PR got merged.


So what we could try to do is:

  1. use diff to find those packages which were changed
  2. use jq to extract provide packages
  3. compare provide constraint with require constraint

Or maybe something else. I'll keep this here to keep track of my ideas.

More integrated integration testing

Feature Request

Q A
New Feature yes

Summary

As of now, we are only integration testing this component by directly executing the main.js which is build inside the container.
However, I've tested the latest v1.12.0 release in one of my projects and directly got the issue which was fixed with #96

This ticket is to keep track that we need a more integrated way of testing this component.

Matrix crashes due to missing json-schema node dependency

Bug Report

Q A
Version(s) 1.8.0

Summary

It seems that the node dependency @cfworker/json-schema is not installed when matrix generation ramps up.

Current behavior

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/action/node_modules/@cfworker/json-schema/src/types' imported from /action/index.js

How to reproduce

Run matrix generation on any project on github which uses this action.

https://github.com/boesing/psalm-plugin-stringf/pull/8/checks?check_run_id=3309644575

Expected behavior

Matrix generation works as expected.

`@lowest` and `@latest` is not respected when project provides explicit `checks`

Bug Report

Q A
Version(s) 1.11.4

Summary

I am currently working on providing integration tests in #62
There, I've seen that @lowest and @latest is not properly handled by the matrix action when it comes to explicit checks provided by the projects .laminas-ci.json

Current behavior

When @lowest and/or @latest is used for job.php, the action does skip that job:

::warning::Invalid job provided; no PHP version or unknown PHP version specified: {"php":"@lowest","dependencies":"locked","command":"vendor/bin/phpunit"}
::warning::Invalid job provided; no PHP version or unknown PHP version specified: {"php":"@latest","dependencies":"locked","command":"vendor/bin/phpunit"}

How to reproduce

.laminas-ci.json
{
    "checks": [
        {
            "name": "PHPUnit with locked dependencies on lowest supported PHP version",
            "job": {
                "php": "@lowest",
                "dependencies": "locked",
                "command": "vendor/bin/phpunit"
            }
        },
        {
            "name": "PHPUnit with locked dependencies on lowest supported PHP version",
            "job": {
                "php": "@latest",
                "dependencies": "locked",
                "command": "vendor/bin/phpunit"
            }
        }
    ]
}

Expected behavior

Matrix does not report a warning for @lowest or @latest and properly uses the lowest and latest supported PHP version by the project within the job declaration.

Pull requests without dedicated branch fail creating the matrix

Bug Report

Q A
Version(s) 1.5.2

Summary

It seems that for pull requests, which are created from the same branch in the forked repository, it is not possible to create a diff for the matrix generation.

Current behavior

Target branch: 1.2.x
Project branch: 1.2.x

Cloning into '.'...
Cloning repository
Checking out branch 1.2.x
Already on '1.2.x'
Your branch is up to date with 'origin/1.2.x'.
Fetching target ref refs/pull/7/merge
fatal: Refusing to fetch into current branch refs/heads/1.2.x of non-bare repository

https://github.com/laminas/laminas-mvc-i18n/pull/7/checks?check_run_id=2254661339

How to reproduce

Fork a repository, do not create a dedicated feature/bugfix/whatever branch but push to the same branch, the PR is targeted to later on.

Expected behavior

Matrix generation works without conflicting when creating a diff.
Works when the source branch differs: https://github.com/laminas/laminas-mvc-i18n/pull/10/checks?check_run_id=2254711601

Merge CI matrix and CI container into the same project

Feature Request

Q A
New Feature yes
RFC kinda
BC Break no

Summary

As suggested by @Ocramius on the laminas Slack: We could think about creating a monorepo for the matrix generation and CI container as they heavily depend on each other.
Even tho, its nice to decouple things, it might be worth merging both projects together.

We can build both containers from within one project and publish these to the github docker repository (I guess?).

Identify a check by name within CI action

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

Hey there,

I am currently working on something and I have the following use-case:

  • run tests on all supported PHP versions (works out-of-the-box)
  • run tests on lowest PHP version with locked deps (works ootb)
  • run tests on lowest PHP version with locked deps via additional_checks (works ootb, but...)

So the latter does work due to prior changes made to this action. The problem is, that I now want to identify this exact additional_check somehow. Because the main idea of this check would be:

Run tests on lowest PHP version with locked deps but disable one or more PHP extensions (to see if tests are still passing due to precautions or polyfills) and/or disallow PHP functions.

So, I'd like to have some kind of optional name within the job configuration which can be used as some kind of unique identifier. When added, this can be extract within a pre-run.sh for example.
An alternative would be to actually allow disabling extensions via the job array. That would make the whole thing easier but maybe its worth having both "features" up and running.

WDYT?

`@highest` value for `php` in `.laminas-ci.json`

Feature Request

Q A
New Feature yes
RFC yes
BC Break yes

Summary

I wonder if thats something we might want to add to allow projects to declare some stuff on the latest PHP version that project is supporting. I don't really have a use-case as of now but having this might probably open up some things for other projects.

So in the end, @highest or @latest in additional_checks would be converted to the highest supported version of a project (as detected in the config).


{
    "additional_checks": [
        {
            "name": "Output version of highest PHP version",
            "job": {"php": "@highest", "command": "php -v"}
        }
    ]
}

Would result in the following, if the php constraint is ^7.3 || ^8.0 (as of v1.10 which only can handle PHP 5.6 - 8.1):

{"php": "8.1", "command": "php -v"}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.