Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESLint, cross-env make, run all tests in 2 minutes (instead of 20) #276

Merged
merged 33 commits into from
Aug 16, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a2df205
Update make, use eslint and other QOL changes
SleeplessByte Jul 24, 2019
95267d0
Implement changes of eslint
SleeplessByte Jul 24, 2019
fe2fdfe
Use package tsc
SleeplessByte Jul 24, 2019
0318209
Fix final files
SleeplessByte Jul 24, 2019
85921ab
Only lint .example and .test
SleeplessByte Jul 24, 2019
7f8dd34
Make two-fer easier
SleeplessByte Jul 24, 2019
e60c311
Remove tslint.json
SleeplessByte Jul 24, 2019
51b275e
Use travis to run danger
SleeplessByte Jul 24, 2019
2a6baf0
Now that travis is danger-only, it should only have one version
SleeplessByte Jul 24, 2019
a9dd70d
Break example to test danger
SleeplessByte Jul 24, 2019
38cca01
Make whitespace resistant
SleeplessByte Jul 25, 2019
48c248d
Use one directory, add commentary and colours
SleeplessByte Jul 25, 2019
3f9b0e6
Cleanup final messages
SleeplessByte Jul 25, 2019
9ff4233
Fix danger
SleeplessByte Jul 25, 2019
66daaee
Remove -n flag
SleeplessByte Jul 25, 2019
9587636
Fix danger again
SleeplessByte Jul 25, 2019
f798cf0
Use right variable
SleeplessByte Jul 25, 2019
889d75e
Use relative paths
SleeplessByte Jul 25, 2019
ca88257
Danger works, fix exercise
SleeplessByte Jul 25, 2019
8f6697e
Use dangerfile dsl
SleeplessByte Jul 25, 2019
f787100
Try to force install LTS node
SleeplessByte Jul 25, 2019
330968c
Print all the files
SleeplessByte Jul 25, 2019
50a6dd2
More printing
SleeplessByte Jul 25, 2019
dd055f8
Does this give a non-relative path?
SleeplessByte Jul 25, 2019
38607c4
Hardcode travis path
SleeplessByte Jul 25, 2019
8d90b0c
Fix syntax error
SleeplessByte Jul 25, 2019
7d625b0
Fix for older ruby
SleeplessByte Jul 25, 2019
d44e2ba
load nvm onto path
SleeplessByte Jul 25, 2019
5e48411
Try nvm as one command
SleeplessByte Jul 25, 2019
6bcbf13
Try brew for node
SleeplessByte Jul 25, 2019
46521a0
Yay. Upgrade node via brew
SleeplessByte Jul 25, 2019
12e9612
macosx support
SleeplessByte Jul 25, 2019
406b3b9
Don't copy node_modules
SleeplessByte Jul 25, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,20 @@ node_modules
build
babel-output
lintreport.json

# These should be placed in common or maintaining. Only have them in the root
# to make editor plugins work.
/.eslintignore
/.eslintrc
/tsconfig.json

# These are artifacts from running make test. They should be removed by make.
# The correct location for these files is the maintaining folder.
/exercises/package.json
/exercises/tsconfig.json
/exercises/.eslint.track.rc
/exercises/.eslintrc
/exercises/.eslintignore
/exercises/yarn.lock
/exercises/node_modules
exercises/yarn-error.log
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- "node"
- "lts/*"

cache: yarn

Expand All @@ -12,11 +12,12 @@ before_install:

before_script:
- npm install -g yarn
- node -v
- yarn -v
- ruby -v

script:
- bin/fetch-configlet
- bin/configlet lint .
- make test

after_success:
- make report
- danger
32 changes: 20 additions & 12 deletions Dangerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,24 @@ if contents.to_s == ''
contents = "[]"
end
json = JSON.parse contents

git_root = __dir__

json.each do |object|
shortFile = object["name"]
shortFile = shortFile.to_s || ''
msg = object["failure"].to_s || ''
line = object["endPosition"]["line"] || 1
#only warn for files that were edited in this PR.
if git.modified_files.include? shortFile
shortFile.prepend("/") # get away from doing inline comments since they are buggy as of Sep-2016
warn(msg, file: shortFile, line: line)
else
message(msg, file: shortFile, line: line)
end
end
source_file = object["filePath"].sub(git_root, '*/').sub('//', '/')

(object["messages"] || []).each do |message|
danger_message = "#{message["message"].to_s} (#{message["ruleId"].to_s})"
source_line = message["line"]

# only warn for files that were edited in this PR.
if git.modified_files.include? source_file
# get away from doing inline comments since they are buggy as of Sep-2016
shortFile.prepend("/") unless source_file[0] == '/'

warn(danger_message, file: source_file, line: source_line)
else
message(danger_message, file: source_file, line: source_line)
end
end
end
290 changes: 220 additions & 70 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,232 @@ IGNOREDIRS := "^(\.git|bin|node_modules|docs|.idea|build)$$"
ASSIGNMENTS = $(shell find ./exercises -maxdepth 1 -mindepth 1 -type d | cut -d'/' -f3 | sort | grep -Ev $(IGNOREDIRS))

#intermediate directories
TMPDIR ?= "/tmp"
INTDIR := $(shell mktemp -d "$(TMPDIR)/$(ASSIGNMENT).XXXXXXXXXX")
INTDIR := $(or $(INTDIR), $(shell mktemp -d))

# language specific config (tweakable per language)
FILEEXT := "ts"
EXAMPLE := "$(ASSIGNMENT).example.$(FILEEXT)"
TSTFILE := "$(ASSIGNMENT).test.$(FILEEXT)"

all: test

test-assignment:
@printf "\e[4mRunning tests for $(ASSIGNMENT) assignment\e[0m\n"
@cp -a common/. $(INTDIR)
@sed 's/\bxit\b/it/g; s/\bxdescribe\b/describe/g' exercises/$(ASSIGNMENT)/$(TSTFILE) > $(INTDIR)/$(TSTFILE)
@cp exercises/$(ASSIGNMENT)/$(EXAMPLE) $(INTDIR)/$(ASSIGNMENT).$(FILEEXT)
@cd $(INTDIR) && yarn install && yarn lintci && yarn test

test:
$(MAKE) checkAllPackageFilesAreTheSame
$(MAKE) checkAllExercisesHaveStubFile
@npm install tslint typescript -g
@tslint './**/*.ts?(x)' -c "./common/tslint.json" --format "json" >> lintreport.json ; exit 0
@for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) test-assignment || exit 1; done


all: moveAllIntoCommonDir
all: moveCommonIntoSubDir

moveAssigmentToSub:
@mv ./common/$(ASSIGNMENT).$(FILEEXT) exercises/$(ASSIGNMENT)/$(EXAMPLE)
@mv ./common/$(TSTFILE) exercises/$(ASSIGNMENT)/$(TSTFILE)

moveAssigmentToCommon:
@mv ./exercises/$(ASSIGNMENT)/$(EXAMPLE) common/$(ASSIGNMENT).$(FILEEXT)
@mv ./exercises/$(ASSIGNMENT)/$(TSTFILE) common/$(TSTFILE)

moveAllIntoCommonDir:
@for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) moveAssigmentToCommon || exit 1; done

moveCommonIntoSubDir:
@for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) moveAssigmentToSub || exit 1; done

all: replacePackageFilesFromCommonToSubFolders

copyPackageFilesToSubFolder:
@cp ./common/package.json exercises/$(ASSIGNMENT)/package.json
@cp ./common/tsconfig.json exercises/$(ASSIGNMENT)/tsconfig.json
@cp ./common/tslint.json exercises/$(ASSIGNMENT)/tslint.json
@cp ./common/yarn.lock exercises/$(ASSIGNMENT)/yarn.lock

replacePackageFilesFromCommonToSubFolders:
@for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) copyPackageFilesToSubFolder || exit 1; done

all: checkAllPackageFilesAreTheSame

checkPackageFilesMach:
@cmp --silent ./common/package.json exercises/$(ASSIGNMENT)/package.json || exit 1;
@cmp --silent ./common/tsconfig.json exercises/$(ASSIGNMENT)/tsconfig.json || exit 1;
@cmp --silent ./common/tslint.json exercises/$(ASSIGNMENT)/tslint.json || exit 1;
@cmp --silent ./common/yarn.lock exercises/$(ASSIGNMENT)/yarn.lock || exit 1;

reportError:
@echo "**Package files in |$(ASSIGNMENT)| are not equal to the |common| folder**" ;
##
# Default task, which runs all the tests, ensures all the configurations are the
# same and checks them. The last two rules are to ensure these make targets are
# actually correct.
#
# make
#
all: test sync-configurations

##
# Test a single assignment
#
# ASSIGNMENT=bob make test-assignment
#
test-assignment: prepare-test-dependencies prepare-test-configuration enable-test-example
@printf "\E[34mRunning tests for '$(ASSIGNMENT)'\E[0;10m\n"
cd "$(INTDIR)" && yarn test && yarn lint:ci
@ASSIGNMENT="$(ASSIGNMENT)" INTDIR="$(INTDIR)" "$(MAKE)" --no-print-directory cleanup-test

##
# Test all the assignments. This is meant for maintainers of the repository.
# Runs through all the different assignments, copies their tests and finally
# runs the equivalent of "make test-assignment" on it.
#
# Note: this works because by definition of how this entire file is set-up, no
# two exercises can have the same name, or colliding files.
#
# make test
#
test: check-stubs check-configurations prepare-test-dependencies prepare-test-configuration
@printf "\E[34mEnabling all tests\E[0;10m\n"
@for assignment in $(ASSIGNMENTS); \
do ASSIGNMENT=$$assignment INTDIR="$(INTDIR)" "$(MAKE)" --no-print-directory enable-test-example || exit 1; \
done
@printf "\E[1K\r\E[34mRunning all tests ($(ASSIGNMENTS))\E[0;10m\n"
cd "$(INTDIR)" && yarn test && yarn lint:ci

##
# Generate a lint report for all .ts(x) files of all exercises. It does so by
# temporarily installing the maintaining configuration in the exercises folder,
# installing the dependencies and running eslint.
#
# make report
#
# If you want this in a human-friendly output, run the following target instead:
#
# make lint-track
#
report:
# Add all the track level configuration
@cp ./maintaining/package.track.json ./exercises/package.json
@cp ./maintaining/tsconfig.track.json ./exercises/tsconfig.json
@cp ./maintaining/.eslint.track.rc ./exercises
@cp ./maintaining/.eslintignore.track ./exercises/.eslintignore

# Create the report
@cd ./exercises && yarn install && yarn lint:report >> /dev/null || exit 0;
@mv ./exercises/lintreport.json ./

# Remove all the track level configuration
@rm -f ./exercises/package.json
@rm -f ./exercises/tsconfig.json
@rm -f ./exercises/.eslint.track.rc
@rm -f ./exercises/.eslintignore
@rm -f ./exercises/yarn.lock
@rm -rf ./exercises/node_modules

lint-track:
# Add all the track level configuration
@cp ./maintaining/package.track.json ./exercises/package.jsonR
@cp ./maintaining/tsconfig.track.json ./exercises/tsconfig.json
@cp ./maintaining/.eslint.track.rc ./exercises
@cp ./maintaining/.eslintignore.track ./exercises/.eslintignore

# Lint everything
@cd ./exercises && yarn install && yarn lint;

# Remove all the track level configuration
@rm -f ./exercises/package.json
@rm -f ./exercises/tsconfig.json
@rm -f ./exercises/.eslint.track.rc
@rm -f ./exercises/.eslintignore
@rm -f ./exercises/yarn.lock
@rm -rf ./exercises/node_modules

##
# Copy the configuration files from the "common" folder to the <exercise> folder
#
# ASSIGNMENT=bob make sync-assignment-configuration
#
sync-assignment-configuration:
@printf "\E[1K\r\E[36mSyncing 'common' configuration to 'exercises/$(ASSIGNMENT)'\E[0;10m"
@cp ./common/.eslintrc "exercises/$(ASSIGNMENT)/.eslintrc"
@cp ./common/.eslintignore "exercises/$(ASSIGNMENT)/.eslintignore"
@cp ./common/jest.config.js "exercises/$(ASSIGNMENT)/jest.config.js"
@cp ./common/package.json "exercises/$(ASSIGNMENT)/package.json"
@cp ./common/tsconfig.json "exercises/$(ASSIGNMENT)/tsconfig.json"
@cp ./common/yarn.lock "exercises/$(ASSIGNMENT)/yarn.lock"

##
# Copy the configuration from the "common" folder to each exercise folder
#
# make sync-configurations
#
sync-configurations:
@printf "\E[34mSyncing 'common' configuration to all assignments\E[0;10m\n"
@for assignment in $(ASSIGNMENTS); \
do ASSIGNMENT=$$assignment "$(MAKE)" --no-print-directory sync-assignment-configuration || exit 1; \
done
@printf "\E[1K\r\E[32mAll exercises have the 'common' configuration\E[0;10m\n"


##
# Syncs the maintaining configuration to the root folder. This may be necessary
# for some IDE's/plugins. For example: there are various eslint plugins that
# will look for the tsconfig relative to the root (interpretation of ./tsconfig)
# instead of relative to .eslintrc.
#
# make sync-maintaining-root
#
sync-maintaining-root:
@cp maintaining/.eslintignore ./
@cp maintaining/.eslint.track.rc ./.eslintrc
@cp maintaining/tsconfig.track.json ./tsconfig.json

#===============================================================================
# HELPER TARGETS
#
# Everything below here are helper functions. You don't need to run these
# targets yourself. They won't do you any good without proper set-up or very
# specific use-cases.
#===============================================================================

##
# Copy the tests for an exericse and enable all the actual tests inside. Also
# copy the example code as if it was the assignment submission.
#
enable-test-example:
@printf "\E[1K\r\E[36mEnabling tests for '$(ASSIGNMENT)' ($(INTDIR))\E[0;10m"
@sed 's/\bxit\b/it/g; s/\bxdescribe\b/describe/g' "exercises/$(ASSIGNMENT)/$(TSTFILE)" > "$(INTDIR)/$(TSTFILE)"
@cp "exercises/$(ASSIGNMENT)/$(EXAMPLE)" "$(INTDIR)/$(ASSIGNMENT).$(FILEEXT)"

##
# Install all the dependencies of "common", which will be used to run the tests.
#
# Note: Because the tests use the maintainers eslint, that eslint can NOT
# contain _more_ dependencies than the common eslint.
#
prepare-test-dependencies:
@printf "\E[34mPreparing test dependencies\E[0;10m\n"
cd ./common && yarn install

##
# Copies the common configuration and maintaining eslint to the test directory.
#
prepare-test-configuration:
@printf "\E[34mPreparing test configuration ($(INTDIR))\E[0;10m\n"
# Copy special maintainers configuration
@cp ./maintaining/.eslint.track.rc "$(INTDIR)/.eslintrc"

# Copy all the configuration from common to temp/<dir>/node_modules
@cp ./common/.eslintignore "$(INTDIR)"
@cp ./common/jest.config.js "$(INTDIR)"
@cp ./common/package.json "$(INTDIR)"
@cp ./common/tsconfig.json "$(INTDIR)"
@cp ./common/yarn.lock "$(INTDIR)"

# Create a symlink from node_modules to temp/<dir>/node_modules
@cp -rl ./common/node_modules "$(INTDIR)/node_modules"

##
# Remove the assignment files, leaving the testing directory configuration
# intact (so it may be re-used).
#
cleanup-test:
@rm "$(INTDIR)/$(ASSIGNMENT).$(FILEEXT)"
@rm "$(INTDIR)/$(TSTFILE)"

##
# Checks if all the package configuration matches common configuration
#
# Note: if this fails, use the following target to fix it:
#
# ASSIGNMENT=failing make sync-assignment-configuration
#
check-assignment-configuration:
@printf "\E[1K\r\E[36mCheck common configuration for '$(ASSIGNMENT)'\E[0;10m"
@cmp --silent ./common/.eslintrc "exercises/$(ASSIGNMENT)/.eslintrc" || exit 1;
@cmp --silent ./common/.eslintignore "exercises/$(ASSIGNMENT)/.eslintignore" || exit 1;
@cmp --silent ./common/jest.config.js "exercises/$(ASSIGNMENT)/jest.config.js" || exit 1;
@cmp --silent ./common/yarn.lock "exercises/$(ASSIGNMENT)/yarn.lock" || exit 1;
@cmp --silent ./common/package.json "exercises/$(ASSIGNMENT)/package.json" || exit 1;
@cmp --silent ./common/tsconfig.json "exercises/$(ASSIGNMENT)/tsconfig.json" || exit 1;
@cmp --silent ./common/yarn.lock "exercises/$(ASSIGNMENT)/yarn.lock" || exit 1;

##
# Checks all the assignments their configuration
check-configurations:
@printf "\E[34mChecking all asignments on their 'common' configuration\E[0;10m\n"
@for assignment in $(ASSIGNMENTS); \
do ASSIGNMENT=$$assignment "$(MAKE)" --no-print-directory check-assignment-configuration || ASSIGNMENT=$$assignment "$(MAKE)" --no-print-directory report-error || exit 1 ; \
done
@printf "\E[1K\r\E[32mAll package configuration matches common configuration\E[0;10m\n"

check-assignment-stub:
@printf "\E[1K\r\E[36mCheck stub for '$(ASSIGNMENT)'\E[0;10m"
@[ -f ./exercises/$(ASSIGNMENT)/$(ASSIGNMENT).$(FILEEXT) ] || exit 1;

check-stubs:
@printf "\E[34mChecking all assignments on their stubs\E[0;10m\n"
@for assignment in $(ASSIGNMENTS); \
do ASSIGNMENT=$$assignment "$(MAKE)" --no-print-directory check-assignment-stub || ASSIGNMENT=$$assignment "$(MAKE)" --no-print-directory report-no-stub || exit 1 ; \
done
@printf "\E[1K\r\E[32mAll exercises contain a stub file (<exercise-name>.ts)\E[0;10m\n"

report-error:
@printf "\E[1K\r\E[31mPackage files in '$(ASSIGNMENT)' are not equal to the 'common' folder\E[0;10m\n";
@exit 1

checkAllPackageFilesAreTheSame:
@for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) checkPackageFilesMach || ASSIGNMENT=$$assignment $(MAKE) reportError || exit 1 ;done
@echo "==All package support files look to be the same as the ones in common=="

reportNoStubFile:
@echo "**Exercise |$(ASSIGNMENT)| does contain a stub file**" ;
report-no-stub:
@printf "\E[1K\r\E[31mExercise '$(ASSIGNMENT)' does contain a stub file ($(ASSIGNMENT).ts)\E[0;10m\n";
@exit 1

checkStubFileExists:
[ -f ./exercises/$(ASSIGNMENT)/$(ASSIGNMENT).$(FILEEXT) ] || exit 1;

checkAllExercisesHaveStubFile:
@for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) checkStubFileExists || ASSIGNMENT=$$assignment $(MAKE) reportNoStubFile || exit 1 ;done
@echo "==All exercises should contain a stub file with the exercise name=="
1 change: 1 addition & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
- run: bin/fetch-configlet
- run: bin/configlet lint . --track-id=typescript
- run: touch Brewfile; echo "brew 'gnu-sed'" >> Brewfile;
- run: brew update
- run: brew bundle
- run: gsed -i 's/@sed/@gsed/g;' Makefile
- run: cat Makefile
Expand Down
Loading