Development on this project uses the GitHub Flow:
- Create your feature branch (
git checkout -b my-new-feature
) - Stage your changes (
git add
) - Commit your JSHint-compliant and test-passing changes (just run
grunt
) with a good commit message (git commit
) - Push to the branch (
git push -u origin my-new-feature
) - Create a new Pull Request
NSIDC's project CI utilizes internal configuration found in the .yaml, Vagrantfile and /puppet/. If you are utilizing this project external to NSIDC you can safely ignore those files and the remainder of this section.
Most projects just have a file called vagrant-nsidc.yaml
, which specifies a
project
name for the plugin to use. This repository really has two projects,
ade_search
and nsidc_search
, configured in vagrant-nsidc.ade_search.yaml
and vagrant-nsidc.nsidc_search.yaml
.
To use the correct config file, set the appropriate environment variable:
export VAGRANT_NSIDC_YAML=vagrant-nsidc.ade_search.yaml
If switching which project you are working on, take care that you are using the
correct config file, and that the temp file .nsidc-project.yaml
references the
right project.
Once that is setup, machines can be provisied as expected using the vagrant-nsidc plugin.
Run grunt tasks
to get a list and descriptions of the most important grunt
tasks defined in Gruntfile.js
. Tasks that should use additional command line
flags list those flags at the end of the description.
The default grunt task (i.e., just running grunt
) runs syntax checkers and
unit tests.
grunt tasks
does not list grunt watch
tasks, and there are a couple of those
that are useful:
grunt watch:lint-test
will automatically run JSHint, scss-lint, and the Jasmine test suite whenever a JavaScript or Sass file is changedgrunt watch:build-$PROJECT
automatically runsgrunt build:$PROJECT-dev
whenever a Sass or Jade file is changed (PROJECT
must beacadis
ornsidc
)
grunt build:nsidc
and grunt build:acadis
will create a build/
directory
containing HTML and CSS files generated from Jade and Sass files, as well as a
minified JavaScript file created by the
RequireJS Optimizer. Other files,
such as external JavaScript libs and image files, are also copied to build/
so
that it contains everything needed to run the interface in a browser. This
directory can then be compressed and used for deployment.
grunt build:nsidc-dev
and grunt build:acadis-dev
skip the RequireJS
optimizer step, and do not create a build/
directory. Instead, the generated
HTML and CSS are kept within src/
.
The environment defaults to development, to set the environment pass an
environment argument to grunt, for example grunt build:nsidc --environment=production
. The CSS generated from the Sass source varies based
on the environment; for production, it will be compressed, otherwise it is more
readable and includes line numbers mapping to the original source files. The
generated HTML also uses the environment to load the appropriate configuration
from src/conf/
.
Run grunt build:nsidc-dev
or grunt build:acadis-dev
to generate the
appropriate src/index.html
file (as well as css files), then
./run_local_webserver.rb
and open your browser to http://localhost:8081.
To run using the code generated by the RequireJS optimizer (concatenated and
minified js, rather than the standard source), modify
local_webserver_config.yaml
to use build/
instead of src/
.
In order for the ADE interface to not run into cross browser scripting issues connecting to the BCube GI-Cat/GI-Axe instances, the nginx conf files must be changed. Theoretically these changes can be included in the Puppet file and automatically deployed but I don't have time to figure out exactly how to do that. Therefore to create proxies you must logon to the VM and add the following to /etc/nginx/nginx.conf: upstream bcube-server { server bcube.geodab.eu; }
upstream bcube-axe-server { server bcubeaxe.geodab.eu; }
and the following to /etc/nginx/sites-enabled/search.conf: location /gi-cat { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-NginX-Proxy true; proxy_pass http://bcube-server/bcube-broker/; }
location /gi-axe { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-NginX-Proxy true; proxy_pass http://bcube-axe-server/bcube-broker-axe/; }
Then nginx must be restarted: sudo service nginx restart
The external services used by the search portal are defined in
local_webserver_config.yaml
. search_proxies
are the default choice, and
contain endpoints for the services running on localhost
. integration_proxies
and qa_proxies
are also defined.
To run against services on integration:
./run_local_webserver.rb 8081 integration_proxies
To run against services on qa:
./run_local_webserver.rb 8081 qa_proxies
Prerequisites
- Firefox
- If using the development VM under Mac OS X, XQuartz is required.
To run the acceptance tests on your machine from the
development VM, you will first need
to ssh with X windowing enabled. Instead of connecting with vagrant ssh
, use
ssh -X [email protected] -p 2222
.
grunt test:acceptance --project=ade_search --environment=integration
project
can be ade_search
or nsidc_search
environment
can be integration
, qa
, or staging
.
The URL used by Cucumber is built from project
and environment
. To test
against a different URL (like when running the tests locally), specify with a
--url
flag (project
must still be specified):
grunt test:acceptance --url=http://localhost:8081 --project=ade_search
- The structure of our Sass code is as follows:
src/sass
_config_*.scss
- contains different variable definitions to separate styles across projects built from the common codebase
*_main.scss
- imports the configuration and modules for that project
modules/
- a Sass module defines the styling for a specific part of the page; keeping our code more modular makes it easier to identify places where it can be shared across projects, and makes it easier to find a particular selector you are interested in modifying or investigating
utilities/
- our own custom Sass functions; no CSS rules are defined in here
junk/
- old, monolithic CSS files converted to Sass syntax still needing
cleanup (break into smaller parts, put those parts in
modules/
)
- old, monolithic CSS files converted to Sass syntax still needing
cleanup (break into smaller parts, put those parts in
grunt sass:dev
generatessrc/css/acadis-search.css
andsrc/css/nsidc-search.css
, combining the project-specifc scss and the common files into onegrunt sass:$PROJECT
generatestmp/css/$PROJECT-search.css
; this is used bygrunt build:$PROJECT
(see the Build section)grunt sass
is configured to compress the generated CSS files and generate source maps, allowing tools like the Chrome Inspector to automatically show line numbers from the original Sass filesgrunt scsslint
runs the scss-lint tool on the Sass files. It is configured by rules inconfig/scss-lint.yml
(with additional rules that should be cleaned up inconfig/scsslint-todo.yml
)- Compass is used to handle cross-browser CSS3 features with less code in the files we write.
- Using Sass requires some gems which can be installed with
bundle install
.
Run the unit tests in PhantomJS with grunt jasmine
. Test code is located in spec/
, written in
Jasmine 1.3 along with
Sinon.
It can helpful for debugging purposes to run the unit tests in a browser. To do so, follow these steps:
- if you don't already have the file
_SpecRunner.html
, rungrunt test:unit
to generate the file - make sure your port 8081 is open (kill the local webserver if you are running it)
grunt serve-tests
- point your browser to localhost:8081/_SpecRunner.html
Run with grunt jshint
. Run automatically whenever a JavaScript file is changed
with grunt watch:jshint
.
JSHint is configured in .jshintrc
, a JSON file containing a list of options
and allowed global variables.
- Official documentation for JSHint configuration options
- Grunt task for JSHint
- JSHint in Emacs with flycheck
- plugins to run JSHint in various editors and IDEs
The acceptance tests use the official
Ruby implementation of Cucumber,
and we use the tool RuboCop to lint the
Ruby code contained within this project. After installing the gems listed in
Gemfile
with bundle install
, RuboCop can be run with bundle exec rubocop
. Settings can be found in .rubocop.yml
.
Our build server attempts to build the project with every revision, and it requires that linters and unit tests pass successfully. To protect yourself from the embarrasment of breaking the build, git hooks can be set up to run everything on your local box before you push.
Git hooks are configured in Gruntfile.js
with the grunt-githooks
plugin. Running grunt githooks
udpates files in your .git/hooks/
so that the
specific grunt tasks will be run at the given git events. This means if the
githooks task configuration is ever changed, you will need to run grunt githooks
again to update your hook scripts (and if a hook is removed the
Gruntfile configuration, you may need to delete the old script from
.git/hooks/
).
Currently included hooks (and the tasks they run) are:
pre-commit
:scsslint
andjshint
pre-push
:jasmine
We are using a customized version of Bootstrap to avoid conflicts with global NSIDC styles included via SSI. To add to the existing set of styles and scripts go to Bootstrap's customize page.
To generate the download, first deselect all items in the "Choose components" and "Select jQuery plugins" sections.
In "Choose components" select the following:
- Base CSS
- Buttons
- Componets
- Button groups and dropdowns
- Alerts
- JS Components
- Dropdowns
In "Select jQuery plugins" select the following:
- Dropdowns
- Buttons
Replace the src/contrib/bootstrap/
directory with the contents of the
downloaded zip file. Be sure to update this list of components after each new
download.
The version in package.json
is updated automatically with the grunt release:$part
task (where $part
is patch
, minor
, or major
). This task
creates a git tag for the new version, and adds 2 new header lines to
CHANGELOG.md
, indicating the version number and the date it was
released. Therefore, new changes should be documented at the top of CHANGELOG.md
without a version header, since it will be added automatically later.