|
| 1 | +--- |
| 2 | +id: ci-workflow |
| 3 | + |
| 4 | +sidebar_label: CI Workflow |
| 5 | + |
| 6 | +title: CI Workflow |
| 7 | +--- |
| 8 | + |
| 9 | +ModuleCheck will automatically fix most issues. Most CI platforms are able to commit changes, and |
| 10 | +automatically cancel out-of-date jobs when the branch has been updated. This tooling can be used to |
| 11 | +apply ModuleCheck's automatic fixes (if any) as part of a CI run, then cancel and start a new run. |
| 12 | +This is similar to a git pre-commit hook, except the work is delegated to a build server. |
| 13 | + |
| 14 | +### Using CI over git hooks |
| 15 | + |
| 16 | +The traditional method for applying changes automatically is with a git hook, such as pre-commit or |
| 17 | +pre-push. But if the task-to-be-automated has a runtime of more than a few seconds, this is a poor |
| 18 | +developer experience. With a CI task, the execution is done automatically and asynchronously, while |
| 19 | +the developer is already moving on to something else. |
| 20 | + |
| 21 | +A git hook also technically doesn't guarantee that a task is executed before code is checked in to a |
| 22 | +main branch, since there's no guarantee that a hook is enabled. With CI, the task will output a |
| 23 | +status check. If a branch protection rule is enabled, that status check can be required. This will |
| 24 | +then guarantee that the task has run (successfully) before any code is checked in to the protected |
| 25 | +branch. |
| 26 | + |
| 27 | +### Example Flow chart |
| 28 | + |
| 29 | +This is a simplified flowchart of how I would run ModuleCheck with unit tests in CI. The |
| 30 | +cancellation, test, and ModuleCheck jobs run in parallel on three different runners. This is an |
| 31 | +"optimistic" workflow, in that it assumes that the `modulecheck` task will not generate changes |
| 32 | +which would trigger a restart. |
| 33 | + |
| 34 | +```mermaid |
| 35 | +flowchart TB |
| 36 | + Start(CI Start):::good --> mGraph |
| 37 | + Start --> tGraph |
| 38 | + Start --> cGraph |
| 39 | +
|
| 40 | + subgraph mGraph [runner 1] |
| 41 | + direction TB |
| 42 | + ModuleCheck(./gradlew moduleCheckAuto):::code --> ChangesModuleCheck |
| 43 | + ChangesModuleCheck{Graph changes?} --- yesM[yes]:::lineLabel --> CommitModuleCheck(Commit changes and push):::stop |
| 44 | + ChangesModuleCheck --- noM[no]:::lineLabel --> EndModuleCheck("#10003;"):::good |
| 45 | + end |
| 46 | +
|
| 47 | + subgraph tGraph [runner 2] |
| 48 | + direction TB |
| 49 | + Tests(./gradlew test):::code --> EndTests("#10003;"):::good |
| 50 | + end |
| 51 | +
|
| 52 | + subgraph cGraph [runner 3] |
| 53 | + direction TB |
| 54 | + Cancel(Cancel previous CI run):::code |
| 55 | + end |
| 56 | +
|
| 57 | + style tGraph fill:#EEE,stroke:#000 |
| 58 | + style cGraph fill:#EEE,stroke:#000 |
| 59 | + style mGraph fill:#EEE,stroke:#000 |
| 60 | +
|
| 61 | + classDef good fill:#0B0,stroke:#000 |
| 62 | + classDef stop fill:#E33,stroke:#000 |
| 63 | +
|
| 64 | + classDef code fill:#AAA,stroke:#000 |
| 65 | +
|
| 66 | + style ChangesModuleCheck fill:#CD1,stroke:#000 |
| 67 | +
|
| 68 | + classDef lineLabel fill:#FFF,stroke:#FFF |
| 69 | +``` |
| 70 | + |
| 71 | +### Example GitHub Action |
| 72 | + |
| 73 | +Here's an Action which will run ModuleCheck, then commit any changes |
| 74 | +using [Stefanzweifel's auto-commit](https://github.com/stefanzweifel/git-auto-commit-action). This |
| 75 | +requires a personal access token secret, or the commit step will fail. |
| 76 | + |
| 77 | +```yaml title=.github/workflows.module-check.yml |
| 78 | +name: ModuleCheck |
| 79 | + |
| 80 | +on: |
| 81 | + pull_request: |
| 82 | + |
| 83 | +jobs: |
| 84 | + |
| 85 | + cancel-stale-jobs: |
| 86 | + name: Cancel stale jobs |
| 87 | + runs-on: ubuntu-latest |
| 88 | + |
| 89 | + steps: |
| 90 | + # cancel previous jobs |
| 91 | + - name: Cancel Previous Runs |
| 92 | + |
| 93 | + env: |
| 94 | + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' |
| 95 | + |
| 96 | + ModuleCheck: |
| 97 | + name: ModuleCheck |
| 98 | + runs-on: ubuntu-latest |
| 99 | + |
| 100 | + steps: |
| 101 | + - uses: actions/checkout@v2 |
| 102 | + with: |
| 103 | + ref: ${{ github.event.pull_request.head.ref }} |
| 104 | + # Must use a personal access token in order to commit changes |
| 105 | + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} |
| 106 | + fetch-depth: 0 |
| 107 | + |
| 108 | + - name: Set up JDK |
| 109 | + uses : actions/setup-java@v2 |
| 110 | + with : |
| 111 | + distribution : 'temurin' |
| 112 | + java-version : '11' |
| 113 | + |
| 114 | + # performs tree-shaking on the Gradle dependency graph |
| 115 | + - name: modulecheck |
| 116 | + run: ./gradlew moduleCheckAuto --no-daemon |
| 117 | + |
| 118 | + # If ModuleCheck generated changes, commit and push those changes. |
| 119 | + # If there are no changes, then this is a no-op. |
| 120 | + - name: commit changes |
| 121 | + uses: stefanzweifel/git-auto-commit-action@v4 |
| 122 | + with: |
| 123 | + commit_message: Apply ModuleCheck changes |
| 124 | + commit_options: '--no-verify --signoff' |
| 125 | + |
| 126 | + tests: |
| 127 | + name: Unit tests |
| 128 | + runs-on: ubuntu-latest |
| 129 | + |
| 130 | + steps: |
| 131 | + - uses: actions/checkout@v2 |
| 132 | + with: |
| 133 | + ref: ${{ github.event.pull_request.head.ref }} |
| 134 | + token: ${{ secrets.GITHUB_TOKEN }} |
| 135 | + fetch-depth: 0 |
| 136 | + |
| 137 | + - name: Set up JDK |
| 138 | + uses : actions/setup-java@v2 |
| 139 | + with : |
| 140 | + distribution : 'temurin' |
| 141 | + java-version : '14' |
| 142 | + |
| 143 | + - name: all tests |
| 144 | + run: ./gradlew test --no-daemon |
| 145 | +``` |
0 commit comments