├── README.md └── action.yml /README.md: -------------------------------------------------------------------------------- 1 | [![Maintained by Redefine.dev](https://img.shields.io/badge/maintained%20by-Redefine.dev-blueviolet)](https://bit.ly/40XeRzi) 2 | 3 | # Redefine GitHub action 4 | 5 | This GitHub Action installs, configures & runs [Redefine](https://bit.ly/3RjVflV) to optimize CI execution time and resources. 6 | 7 | ## Usage 8 | 9 | ```yaml 10 | - name: Redefine GitHub Action 11 | id: redefine 12 | uses: redefinedev/redefine-action@main 13 | with: 14 | # Redefine authentication key given by Redefine in the subscription process, stored as a secret. 15 | auth: ${{ secrets.REDEFINE_AUTH }} 16 | # Python virtual environment path 17 | python-venv-path: .venv/ 18 | # Testing framework to optimize 19 | testing-framework: pytest 20 | # Redefine mode as described in https://docs.redefine.dev/configuration/selection-modes 21 | mode: fail-fast 22 | # The maximum time to run tests with Redefine optimization 23 | time-limit: 300 24 | ``` 25 | 26 | ## Inputs 27 | 28 | ### Parameters 29 | 30 | name|description|default| 31 | |---|---|---| 32 | |`auth`|Redefine authentication key given in by Redefine in the onboarding process|-| 33 | |`testing-framework`|The [testing framework](https://docs.redefine.dev/integrations/supported-technologies) to optimize.|-| 34 | |`command`|Redefine CLI command, one of "[`install`](https://docs.redefine.dev/configuration/install-command)", "[`verify`](https://docs.redefine.dev/welcome-to-redefine/quick-start#verify)", "[`get session_id`](https://docs.redefine.dev/configuration/remote-workers#configure-a-shared-session-id)", "[`get session_check`](https://docs.redefine.dev/configuration/remote-workers#session-check-command)".|`install`| 35 | |`mode`|Redefine execution mode, on of "[`discover`](https://docs.redefine.dev/configuration/selection-modes/discover)", "[`prioritize`](https://docs.redefine.dev/configuration/selection-modes/prioritize)", "[`fail-fast`](https://docs.redefine.dev/configuration/selection-modes/fail-fast)", "[`optimize`](https://docs.redefine.dev/configuration/selection-modes/optimize)".|`discover`| 36 | |`python-venv-path`|Python virtual environment to install Redefine in.|-| 37 | |`time-limit`|The [time limit](https://docs.redefine.dev/configuration/configuration-parameters#time-limit) for running Redefine.|-| 38 | |`min-accuracy`|The [minimum accuracy](https://docs.redefine.dev/configuration/configuration-parameters#minumum-accuracy) for Redefine to achieve.|-| 39 | |`confidence`|The [Confidence](https://docs.redefine.dev/configuration/configuration-parameters#confidence) level for Redefine's prediction.|-| 40 | |`session-id`|The [session ID](https://docs.redefine.dev/configuration/remote-workers#configure-a-shared-session-id) unique for all workers in the run|-| 41 | |`config-args`|[Additional arguments](https://docs.redefine.dev/configuration/configuration-parameters) to pass to the `config set` command in format of key1=value1 key2="long value2" ...|-| 42 | |`split`|The number of machines to split the tests between, when using [Redefine Parallel](https://docs.redefine.dev/configuration/parallel-test-execution/redefine-parallel)|-| 43 | |`group`|The machine index when using [Redefine Parallel](https://docs.redefine.dev/configuration/parallel-test-execution/redefine-parallel)|-| 44 | |`args`|Additional arguments to pass to the redefine command.|-| | - | 45 | ## Examples 46 | 47 | ### Example usage for Github Actions 48 | 49 | ```yaml 50 | name: Redefine 51 | 52 | # Controls when the workflow will run 53 | on: 54 | # Triggers the workflow on pull request events where "main" is the target (base) branch 55 | pull_request: 56 | branches: ["main"] 57 | 58 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 59 | jobs: 60 | # This workflow contains a single job called "pytest" 61 | pytest: 62 | # The type of runner that the job will run on 63 | runs-on: ubuntu-latest 64 | 65 | # Steps represent a sequence of tasks that will be executed as part of the job 66 | steps: 67 | # Checks-out your repository under $GITHUB_WORKSPACE, so follow-up steps can access it 68 | - uses: actions/checkout@v3 69 | - name: Set up Python 70 | uses: actions/setup-python@v4 71 | with: 72 | python-version: 3.11 73 | 74 | # Install python dependencies 75 | - name: Install dependencies 76 | run: pip install -r requirements.txt 77 | 78 | - name: Redefine Start 79 | id: redefine 80 | uses: redefinedev/redefine-action@main 81 | with: 82 | # Redefine authentication key given by Redefine in the subscription process, stored as a secret. 83 | auth: ${{ secrets.REDEFINE_AUTH }} 84 | # Python virtual environment path 85 | python-venv-path: .venv/ 86 | # Testing framework to optimize 87 | testing-framework: pytest 88 | # Redefine mode as described in https://docs.redefine.dev/configuration/selection-modes 89 | mode: fail-fast 90 | # The maximum time to run tests with Redefine optimization 91 | time-limit: 300 92 | 93 | # Execute pytest tests with Redefine 94 | - name: Run pytest 95 | run: pytest -n auto tests/ 96 | ``` 97 | 98 | Note that this example uses the latest version (`main`). It is recommended to use this version instead of a static one to avoid deprecation. 99 | 100 | ### Example usage for Github Actions with pipenv 101 | 102 | ```yaml 103 | name: Redefine 104 | 105 | # Controls when the workflow will run 106 | on: 107 | # Triggers the workflow on pull request events where "main" is the target (base) branch 108 | pull_request: 109 | branches: ["main"] 110 | 111 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 112 | jobs: 113 | # This workflow contains a single job called "pytest" 114 | pytest: 115 | # The type of runner that the job will run on 116 | runs-on: ubuntu-latest 117 | 118 | # Steps represent a sequence of tasks that will be executed as part of the job 119 | steps: 120 | # Checks-out your repository under $GITHUB_WORKSPACE, so follow-up steps can access it 121 | - uses: actions/checkout@v3 122 | 123 | # Installs Python with pipenv cache 124 | - name: Set up Python 125 | uses: actions/setup-python@v4 126 | with: 127 | python-version: 3.11 128 | cache: "pipenv" 129 | cache-dependency-path: "Pipfile.lock" 130 | 131 | # Installs pipenv and other dependencies 132 | - name: Install pipenv 133 | run: | 134 | python -m pip install --no-cache-dir --upgrade pipenv 135 | pipenv install --dev -v 136 | 137 | # Get VENV path 138 | - name: Get venv path 139 | id: get-venv 140 | run: | 141 | echo "venv_path=$(pipenv --venv)" >> $GITHUB_OUTPUT 142 | 143 | - name: Redefine Start 144 | id: redefine 145 | uses: redefinedev/redefine-action@main 146 | with: 147 | # Redefine authentication key given by Redefine in the subscription process, stored as a secret. 148 | auth: ${{ secrets.REDEFINE_AUTH }} 149 | # Python virtual environment path 150 | python-venv-path: ${{ steps.get-venv.outputs.venv_path }} 151 | # Testing framework to optimize 152 | testing-framework: pytest 153 | # Redefine mode as described in https://docs.redefine.dev/configuration/selection-modes 154 | mode: fail-fast 155 | # The maximum time to run tests with Redefine optimization 156 | time-limit: 300 157 | 158 | # Execute pytest tests with Redefine 159 | - name: Run pytest 160 | run: pytest -n auto tests/ 161 | ``` 162 | 163 | ### Example usage for Github Actions with poetry 164 | 165 | ```yaml 166 | name: Redefine 167 | 168 | # Controls when the workflow will run 169 | on: 170 | # Triggers the workflow on pull request events where "main" is the target (base) branch 171 | pull_request: 172 | branches: ["main"] 173 | 174 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 175 | jobs: 176 | # This workflow contains a single job called "pytest" 177 | pytest: 178 | # The type of runner that the job will run on 179 | runs-on: ubuntu-latest 180 | 181 | # Steps represent a sequence of tasks that will be executed as part of the job 182 | steps: 183 | # Checks-out your repository under $GITHUB_WORKSPACE, so follow-up steps can access it 184 | - uses: actions/checkout@v3 185 | 186 | # Installs Python with poetry cache 187 | - name: Set up Python 188 | uses: actions/setup-python@v4 189 | with: 190 | python-version: 3.11 191 | cache: "poetry" 192 | cache-dependency-path: "poetry.lock" 193 | 194 | # Installs poetry and other dependencies 195 | - name: Install poetry 196 | run: | 197 | curl https://install.python-poetry.org | python3 - 198 | echo "$HOME/.local/bin" >> $GITHUB_PATH 199 | poetry install 200 | 201 | # Get VENV path 202 | - name: Get venv path 203 | id: get-venv 204 | run: | 205 | echo "venv_path=$(poetry env info -p)" >> $GITHUB_OUTPUT 206 | 207 | - name: Redefine Start 208 | id: redefine 209 | uses: redefinedev/redefine-action@main 210 | with: 211 | # Redefine authentication key given by Redefine in the subscription process, stored as a secret. 212 | auth: ${{ secrets.REDEFINE_AUTH }} 213 | # Python virtual environment path 214 | python-venv-path: ${{ steps.get-venv.outputs.venv_path }} 215 | # Testing framework to optimize 216 | testing-framework: pytest 217 | # Redefine mode as described in https://docs.redefine.dev/configuration/selection-modes 218 | mode: fail-fast 219 | # The maximum time to run tests with Redefine optimization 220 | time-limit: 300 221 | 222 | # Execute pytest tests with Redefine 223 | - name: Run pytest 224 | run: pytest -n auto tests/ 225 | ``` 226 | 227 | ### Example usage for Github Actions with Redefine Parallel 228 | 229 | ```yaml 230 | name: Redefine 231 | 232 | # Controls when the workflow will run 233 | on: 234 | # Triggers the workflow on pull request events where "main" is the target (base) branch 235 | pull_request: 236 | branches: [ "main" ] 237 | 238 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 239 | jobs: 240 | # This workflow contains a single job called "pytest" 241 | pytest: 242 | # Steps represent a sequence of tasks that will be executed as part of the job 243 | strategy: 244 | # Create a uniques index for each machine 245 | matrix: 246 | group: [ 0, 1, 2 ] 247 | steps: 248 | # Checks-out your repository under $GITHUB_WORKSPACE, so follow-up steps can access it 249 | - uses: actions/checkout@v3 250 | 251 | # Installs Python with poetry cache 252 | - name: Set up Python 253 | uses: actions/setup-python@v4 254 | with: 255 | python-version: 3.11 256 | 257 | 258 | - name: Redefine Start 259 | id: redefine 260 | uses: redefinedev/redefine-action@main 261 | with: 262 | # Redefine authentication key given by Redefine in the subscription process, stored as a secret. 263 | auth: ${{ secrets.REDEFINE_AUTH }} 264 | # Testing framework to optimize 265 | testing-framework: pytest 266 | # Redefine mode as described in https://docs.redefine.dev/configuration/selection-modes 267 | mode: optimize 268 | # Create a unique session ID for the workers to use 269 | # The session ID should be unique for each run 270 | session-id: ${{ github.run_id }}_${{ github.run_attempt }} 271 | # number of machines to split the tests, in this example 3 272 | split: 3 273 | # the machine "index" 274 | group: ${{ matrix.group }} 275 | 276 | 277 | # Execute pytest tests with Redefine 278 | # Redefine will distribute the tests between the machines 279 | - name: Run pytest dry run 280 | run: | 281 | pytest tests/ 282 | 283 | ``` 284 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: redefine-action 2 | 3 | description: Redefine is a CI Optimization platform for increased development velocity and experience 4 | 5 | inputs: 6 | auth: 7 | description: "Redefine auth" 8 | required: true 9 | testing-framework: 10 | description: "The testing framework to optimize." 11 | required: false 12 | enum: ["pytest", "cypress"] 13 | command: 14 | description: "Redefine CLI command to perform." 15 | required: false 16 | default: "install" 17 | enum: 18 | ["install", "verify", "get session_check", "get session_id", "predict"] 19 | mode: 20 | description: "Redefine execution mode." 21 | required: false 22 | default: "discover" 23 | enum: ["discover", "prioritize", "optimize", "fail-fast", "worker"] 24 | python-venv-path: 25 | description: "Python virtual environment to install Redefine in." 26 | required: false 27 | time-limit: 28 | description: "The time limit for running Redefine." 29 | required: false 30 | min-accuracy: 31 | description: "The minimum accuracy for Redefine to achieve." 32 | required: false 33 | confidence: 34 | description: "Redefine confidence level." 35 | required: false 36 | enum: ["low", "high", "normal"] 37 | session-id: 38 | description: "The session ID matching between the orchestrator and the workers" 39 | required: false 40 | output-path: 41 | description: "Path to where the predicted tests will be written to in the format of a '\n' divided list" 42 | required: false 43 | predict-command: 44 | description: "Testing framework command to execute, for example: 'npx cypress run'" 45 | required: false 46 | timeout: 47 | description: "Timeout for the testing framework invocation command, default to 10 seconds" 48 | required: false 49 | default: 10 50 | exit-code: 51 | description: "Return exit code" 52 | required: false 53 | type: boolean 54 | default: false 55 | split: 56 | description: "When using Redefine Parallel, determines how many workers to split the tests into" 57 | required: false 58 | group: 59 | description: "When using Redefine Parallel, determines what group (index) the worker belongs to" 60 | required: false 61 | config-args: 62 | description: "Additional arguments to pass to the `config set` command in format of key1=value1 key2='long value2' ..." 63 | required: false 64 | args: 65 | description: "Additional arguments to pass to the main command." 66 | required: false 67 | 68 | outputs: 69 | session-check: 70 | description: "`get session_check` command result. True if the session is still ongoing, false otherwise." 71 | value: ${{ steps.run-redefine.outputs.session-check }} 72 | session-id: 73 | description: "Session ID generated by 'get session_id' command" 74 | value: ${{ steps.run-redefine.outputs.session-id }} 75 | 76 | branding: 77 | icon: "fast-forward" 78 | color: "purple" 79 | 80 | runs: 81 | using: "composite" 82 | steps: 83 | - name: Run Redefine 84 | id: run-redefine 85 | shell: bash 86 | env: 87 | REDEFINE_AUTH: ${{ inputs.auth }} 88 | REDEFINE_SESSION_ID: ${{ inputs.session-id }} 89 | run: | 90 | if [ -z ${REDEFINE_SESSION_ID} ]; then 91 | # If session-id is empty we don't want an empty environment variable 92 | unset REDEFINE_SESSION_ID 93 | elif [ ${REDEFINE_SESSION_ID} = "UNUSED" ]; then 94 | # If session-id is UNUSED we don't want an empty environment variable 95 | echo "Aborting due to empty session-id, please make sure you configured the session-id properly" 96 | exit 1 97 | fi 98 | 99 | # Activate virtual environment 100 | if [ -n "${{ inputs.python-venv-path }}" ]; then 101 | source ${{ inputs.python-venv-path }}/bin/activate 102 | fi 103 | 104 | if ! redefine --version; then 105 | echo "Installing Redefine..." 106 | pip install -U --no-cache-dir --force-reinstall redefine 107 | fi 108 | 109 | # Prep `redefine config set` command 110 | CONFIG_ARGS="" 111 | 112 | if [ -n "${{ inputs.time-limit }}" ]; then 113 | CONFIG_ARGS="${CONFIG_ARGS} time_limit=${{ inputs.time-limit }}" 114 | fi 115 | 116 | if [ -n "${{ inputs.min-accuracy }}" ]; then 117 | CONFIG_ARGS="${CONFIG_ARGS} min_accuracy=${{ inputs.min-accuracy }}" 118 | fi 119 | 120 | if [ -n "${{ inputs.confidence }}" ]; then 121 | CONFIG_ARGS="${CONFIG_ARGS} confidence=${{ inputs.confidence }}" 122 | fi 123 | 124 | CONFIG_ARGS="${CONFIG_ARGS} ${{ inputs.config-args }}" 125 | 126 | # Run redefine config set 127 | if [ -n "${CONFIG_ARGS}" ]; then 128 | echo "Running: redefine config set ${CONFIG_ARGS}" 129 | redefine config set ${CONFIG_ARGS} 130 | fi 131 | 132 | # Prep Redefine CLI command 133 | CMD_ARGS="${{ inputs.command }}" 134 | 135 | # if command is "install"/"predict"/"verify", add the testing framework 136 | if [ "${{ inputs.command }}" = "install" ] || [ "${{ inputs.command }}" = "verify" ] || [ "${{ inputs.command }}" = "predict" ]; then 137 | 138 | # Will fail at redefine command if missing, no need to add verification here. 139 | if [ -n "${{ inputs.testing-framework }}" ]; then 140 | CMD_ARGS="${CMD_ARGS} --${{ inputs.testing-framework }}" 141 | fi 142 | fi 143 | 144 | # if command is "install"/"predict", add the mode 145 | if [ "${{ inputs.command }}" = "install" ] || [ "${{ inputs.command }}" = "predict" ]; then 146 | 147 | # Will fail at redefine command if missing, no need to add verification here. 148 | if [ -n "${{ inputs.mode }}" ]; then 149 | CMD_ARGS="${CMD_ARGS} --${{ inputs.mode }}" 150 | fi 151 | fi 152 | 153 | # Add exit code arg to "install" command if needed 154 | if [ "${{ inputs.command }}" = "install" ] && [ ${{ inputs.exit-code }} = true ]; then 155 | CMD_ARGS="${CMD_ARGS} --exit-code" 156 | fi 157 | 158 | # if command is "verify" in "worker" mode, add the mode 159 | if [ "${{ inputs.command }}" = "verify" ] || [ "${{ inputs.mode }}" = "worker" ]; then 160 | 161 | # Will fail at redefine command if missing, no need to add verification here. 162 | if [ -n "${{ inputs.mode }}" ]; then 163 | CMD_ARGS="${CMD_ARGS} --${{ inputs.mode }}" 164 | fi 165 | fi 166 | 167 | 168 | # if command is "predict", add prediction output path and command 169 | if [ "${{ inputs.command }}" = "predict" ]; then 170 | # Will fail at redefine command if missing, no need to add verification here. 171 | if [ -n "${{ inputs.output-path }}" ]; then 172 | CMD_ARGS="${CMD_ARGS} --output-path=${{ inputs.output-path }}" 173 | fi 174 | if [ -n "${{ inputs.predict-command }}" ]; then 175 | CMD_ARGS="${CMD_ARGS} --command=\"${{ inputs.predict-command }}\"" 176 | fi 177 | # has default, no need to check if set 178 | CMD_ARGS="${CMD_ARGS} --timeout=${{ inputs.timeout }}" 179 | fi 180 | 181 | # if the user passed "split" and "group" arguments, add them to the command 182 | if [ -n "${{ inputs.split }}" ]; then 183 | CMD_ARGS="${CMD_ARGS} --split=${{ inputs.split }}" 184 | fi 185 | if [ -n "${{ inputs.group }}" ]; then 186 | CMD_ARGS="${CMD_ARGS} --group=${{ inputs.group }}" 187 | fi 188 | 189 | CMD_ARGS="${CMD_ARGS} ${{ inputs.args }}" 190 | 191 | # Run Redefine 192 | echo "Running: redefine ${CMD_ARGS}" 193 | OUTPUT=$(redefine ${CMD_ARGS}) 194 | 195 | # Set the output variable in case command is `get session_check` 196 | if [ "${{ inputs.command }}" = "get session_check" ] && [ $? -eq 0 ]; then 197 | echo "session-check=true" >> "$GITHUB_OUTPUT" 198 | else 199 | # All commands other than `get session_check` set session-check to false 200 | echo "session-check=false" >> "$GITHUB_OUTPUT" 201 | fi 202 | 203 | # Set the output variable in case command is `get session_id` 204 | if [ "${{ inputs.command }}" = "get session_id" ]; then 205 | echo "session-id=$OUTPUT" >> "$GITHUB_OUTPUT" 206 | else 207 | # All commands other than `get session_id` set session-id to UNUSED 208 | echo "session-id=UNUSED" >> "$GITHUB_OUTPUT" 209 | fi 210 | --------------------------------------------------------------------------------