mirror of
				https://github.com/theoludwig/programming-challenges.git
				synced 2025-09-11 23:11:21 +02:00 
			
		
		
		
	fix(cli): add timeout for running solutions
This commit is contained in:
		
							
								
								
									
										45
									
								
								.github/workflows/challenges.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/challenges.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | name: 'challenges' | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: [master] | ||||||
|  |   pull_request: | ||||||
|  |     branches: [master] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   test-solutions: | ||||||
|  |     runs-on: 'ubuntu-latest' | ||||||
|  |     steps: | ||||||
|  |       - uses: 'actions/checkout@v2' | ||||||
|  |         with: | ||||||
|  |           fetch-depth: 0 | ||||||
|  |  | ||||||
|  |       - name: 'Use Docker' | ||||||
|  |         uses: 'actions-hub/docker/cli@master' | ||||||
|  |         env: | ||||||
|  |           SKIP_LOGIN: true | ||||||
|  |  | ||||||
|  |       - name: 'Use Node.js' | ||||||
|  |         uses: 'actions/setup-node@v2.5.0' | ||||||
|  |         with: | ||||||
|  |           node-version: '16.x' | ||||||
|  |           cache: 'npm' | ||||||
|  |  | ||||||
|  |       - name: 'Install' | ||||||
|  |         run: 'npm install' | ||||||
|  |  | ||||||
|  |       - name: 'Build' | ||||||
|  |         run: 'npm run build' | ||||||
|  |  | ||||||
|  |       - name: 'Install programming-challenges' | ||||||
|  |         run: 'npm install --global' | ||||||
|  |  | ||||||
|  |       - uses: 'nrwl/last-successful-commit-action@v1' | ||||||
|  |         id: 'last_successful_commit' | ||||||
|  |         with: | ||||||
|  |           branch: 'master' | ||||||
|  |           workflow_id: 'ci.yml' | ||||||
|  |           github_token: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|  |       - name: 'Test' | ||||||
|  |         run: 'programming-challenges run test --affected --ci --base=${{ steps.last_successful_commit.outputs.commit_hash }}' | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| name: 'ci' | name: 'cli' | ||||||
| 
 | 
 | ||||||
| on: | on: | ||||||
|   push: |   push: | ||||||
| @@ -64,40 +64,3 @@ jobs: | |||||||
| 
 | 
 | ||||||
|       - name: 'Test' |       - name: 'Test' | ||||||
|         run: 'npm run test' |         run: 'npm run test' | ||||||
| 
 |  | ||||||
|   challenges: |  | ||||||
|     runs-on: 'ubuntu-latest' |  | ||||||
|     steps: |  | ||||||
|       - uses: 'actions/checkout@v2' |  | ||||||
|         with: |  | ||||||
|           fetch-depth: 0 |  | ||||||
| 
 |  | ||||||
|       - name: 'Use Docker' |  | ||||||
|         uses: 'actions-hub/docker/cli@master' |  | ||||||
|         env: |  | ||||||
|           SKIP_LOGIN: true |  | ||||||
| 
 |  | ||||||
|       - name: 'Use Node.js' |  | ||||||
|         uses: 'actions/setup-node@v2.5.0' |  | ||||||
|         with: |  | ||||||
|           node-version: '16.x' |  | ||||||
|           cache: 'npm' |  | ||||||
| 
 |  | ||||||
|       - name: 'Install' |  | ||||||
|         run: 'npm install' |  | ||||||
| 
 |  | ||||||
|       - name: 'Build' |  | ||||||
|         run: 'npm run build' |  | ||||||
| 
 |  | ||||||
|       - name: 'Install programming-challenges' |  | ||||||
|         run: 'npm install --global' |  | ||||||
| 
 |  | ||||||
|       - uses: 'nrwl/last-successful-commit-action@v1' |  | ||||||
|         id: 'last_successful_commit' |  | ||||||
|         with: |  | ||||||
|           branch: 'master' |  | ||||||
|           workflow_id: 'ci.yml' |  | ||||||
|           github_token: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
| 
 |  | ||||||
|       - name: 'Test' |  | ||||||
|         run: 'programming-challenges run test --affected --ci --base=${{ steps.last_successful_commit.outputs.commit_hash }}' |  | ||||||
| @@ -1,7 +0,0 @@ | |||||||
| # sorting-algorithms/python/bubble-sort |  | ||||||
|  |  | ||||||
| Created by [@Divlo](https://github.com/Divlo) on 29 June 2021. |  | ||||||
|  |  | ||||||
| | Algorithm                                                   | Best Case   | Average Case | Worst Case  | |  | ||||||
| | ----------------------------------------------------------- | ----------- | ------------ | ----------- | |  | ||||||
| | [Bubble sort](https://wikipedia.org/wiki/Bubble_sort)       | O(n)        | O(n²)        | O(n²)       | |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| from typing import List |  | ||||||
| import sys |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def bubble_sort(numbersInput: List[int]) -> List[int]: |  | ||||||
|     numbers = list(numbersInput) |  | ||||||
|     length = len(numbers) |  | ||||||
|     for index_1 in range(length): |  | ||||||
|         for index_2 in range(length - index_1 - 1): |  | ||||||
|             if numbers[index_2] > numbers[index_2 + 1]: |  | ||||||
|                 temporary = numbers[index_2] |  | ||||||
|                 numbers[index_2] = numbers[index_2 + 1] |  | ||||||
|                 numbers[index_2 + 1] = temporary |  | ||||||
|     return numbers |  | ||||||
|  |  | ||||||
|  |  | ||||||
| numbers: List[int] = [] |  | ||||||
| for value in sys.stdin: |  | ||||||
|     numbers.append(int(value.rstrip('\n'))) |  | ||||||
|  |  | ||||||
| numbers = numbers[1:] |  | ||||||
| sorted_numbers = bubble_sort(numbers) |  | ||||||
| for number in sorted_numbers: |  | ||||||
|     print(number) |  | ||||||
| @@ -1,7 +0,0 @@ | |||||||
| # sorting-algorithms/python/insertion-sort |  | ||||||
|  |  | ||||||
| Created by [@Divlo](https://github.com/Divlo) on 29 June 2021. |  | ||||||
|  |  | ||||||
| | Algorithm                                                   | Best Case   | Average Case | Worst Case  | |  | ||||||
| | ----------------------------------------------------------- | ----------- | ------------ | ----------- | |  | ||||||
| | [Insertion sort](https://wikipedia.org/wiki/Insertion_sort) | O(n)        | O(n²)        | O(n²)       | |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| from typing import List |  | ||||||
| import sys |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def insertion_sort(numbersInput: List[int]) -> List[int]: |  | ||||||
|     numbers = list(numbersInput) |  | ||||||
|     for index_1 in range(1, len(numbers)): |  | ||||||
|         current = numbers[index_1] |  | ||||||
|         index_2 = index_1 - 1 |  | ||||||
|         while index_2 >= 0 and numbers[index_2] > current: |  | ||||||
|             numbers[index_2 + 1] = numbers[index_2] |  | ||||||
|             index_2 -= 1 |  | ||||||
|         numbers[index_2 + 1] = current |  | ||||||
|     return numbers |  | ||||||
|  |  | ||||||
|  |  | ||||||
| numbers: List[int] = [] |  | ||||||
| for value in sys.stdin: |  | ||||||
|     numbers.append(int(value.rstrip('\n'))) |  | ||||||
|  |  | ||||||
| numbers = numbers[1:] |  | ||||||
| sorted_numbers = insertion_sort(numbers) |  | ||||||
| for number in sorted_numbers: |  | ||||||
|     print(number) |  | ||||||
| @@ -1,2 +1,3 @@ | |||||||
| const ONE_MINUTE_IN_MILLISECONDS = 60 * 1000 | import { Docker } from '../services/Docker' | ||||||
| jest.setTimeout(ONE_MINUTE_IN_MILLISECONDS) |  | ||||||
|  | jest.setTimeout(Docker.MAXIMUM_TIMEOUT_MILLISECONDS) | ||||||
|   | |||||||
| @@ -1,9 +1,12 @@ | |||||||
| import execa from 'execa' | import execa from 'execa' | ||||||
| import ora from 'ora' | import ora from 'ora' | ||||||
|  | import ms from 'ms' | ||||||
|  |  | ||||||
| class Docker { | export class Docker { | ||||||
|   static CONTAINER_TAG = 'programming-challenges' |   static CONTAINER_TAG = 'programming-challenges' | ||||||
|   static SIGSEGV_EXIT_CODE = 139 |   static SIGSEGV_EXIT_CODE = 139 | ||||||
|  |   static MAXIMUM_TIMEOUT = '1 minute' | ||||||
|  |   static MAXIMUM_TIMEOUT_MILLISECONDS = ms(Docker.MAXIMUM_TIMEOUT) | ||||||
|  |  | ||||||
|   public async build (): Promise<void> { |   public async build (): Promise<void> { | ||||||
|     const loader = ora('Building the Docker image').start() |     const loader = ora('Building the Docker image').start() | ||||||
| @@ -23,13 +26,22 @@ class Docker { | |||||||
|         input |         input | ||||||
|       } |       } | ||||||
|     ) |     ) | ||||||
|  |     let isValid = true | ||||||
|  |     const timeout = setTimeout(() => { | ||||||
|  |       subprocess.kill() | ||||||
|  |       isValid = false | ||||||
|  |     }, Docker.MAXIMUM_TIMEOUT_MILLISECONDS) | ||||||
|     try { |     try { | ||||||
|       const { stdout, stderr } = await subprocess |       const { stdout, stderr } = await subprocess | ||||||
|       if (stderr.length !== 0) { |       if (stderr.length !== 0) { | ||||||
|         throw new Error(stderr) |         throw new Error(stderr) | ||||||
|       } |       } | ||||||
|  |       clearTimeout(timeout) | ||||||
|       return stdout |       return stdout | ||||||
|     } catch (error: any) { |     } catch (error: any) { | ||||||
|  |       if (!isValid) { | ||||||
|  |         throw new Error(`Timeout: time limit exceeded (${Docker.MAXIMUM_TIMEOUT}), try to optimize your solution.`) | ||||||
|  |       } | ||||||
|       if (error.exitCode === Docker.SIGSEGV_EXIT_CODE) { |       if (error.exitCode === Docker.SIGSEGV_EXIT_CODE) { | ||||||
|         throw new Error('Docker run failed: SIGSEGV indicates a segmentation fault (attempts to access a memory location that it\'s not allowed to access).') |         throw new Error('Docker run failed: SIGSEGV indicates a segmentation fault (attempts to access a memory location that it\'s not allowed to access).') | ||||||
|       } |       } | ||||||
|   | |||||||
							
								
								
									
										747
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										747
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							| @@ -42,7 +42,7 @@ | |||||||
|     "execa": "5.1.1", |     "execa": "5.1.1", | ||||||
|     "ora": "5.4.1", |     "ora": "5.4.1", | ||||||
|     "replace-in-file": "6.3.2", |     "replace-in-file": "6.3.2", | ||||||
|     "table": "6.7.3", |     "table": "6.7.5", | ||||||
|     "typanion": "3.7.1", |     "typanion": "3.7.1", | ||||||
|     "validate-npm-package-name": "3.0.0" |     "validate-npm-package-name": "3.0.0" | ||||||
|   }, |   }, | ||||||
| @@ -52,15 +52,17 @@ | |||||||
|     "@types/date-and-time": "0.13.0", |     "@types/date-and-time": "0.13.0", | ||||||
|     "@types/jest": "27.0.3", |     "@types/jest": "27.0.3", | ||||||
|     "@types/mock-fs": "4.13.1", |     "@types/mock-fs": "4.13.1", | ||||||
|     "@types/node": "16.11.11", |     "@types/ms": "0.7.31", | ||||||
|  |     "@types/node": "16.11.12", | ||||||
|     "@types/validate-npm-package-name": "3.0.3", |     "@types/validate-npm-package-name": "3.0.3", | ||||||
|     "editorconfig-checker": "4.0.2", |     "editorconfig-checker": "4.0.2", | ||||||
|     "get-stream": "6.0.1", |     "get-stream": "6.0.1", | ||||||
|     "jest": "27.4.2", |     "jest": "27.4.3", | ||||||
|     "markdownlint-cli": "0.30.0", |     "markdownlint-cli": "0.30.0", | ||||||
|     "mock-fs": "5.1.2", |     "mock-fs": "5.1.2", | ||||||
|  |     "ms": "2.1.3", | ||||||
|     "rimraf": "3.0.2", |     "rimraf": "3.0.2", | ||||||
|     "ts-jest": "27.0.7", |     "ts-jest": "27.1.0", | ||||||
|     "ts-standard": "11.0.0", |     "ts-standard": "11.0.0", | ||||||
|     "typescript": "4.5.2" |     "typescript": "4.5.2" | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user