ci: Run npm registry in Docker
This commit is contained in:
		
							parent
							
								
									0c67ba517f
								
							
						
					
					
						commit
						40c58c9b42
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -129,7 +129,3 @@ $RECYCLE.BIN/ | |||||||
| 
 | 
 | ||||||
| package-lock.json | package-lock.json | ||||||
| yarn.lock | yarn.lock | ||||||
| 
 |  | ||||||
| # Registry tests |  | ||||||
| test/helpers/registry/couch |  | ||||||
| test/helpers/registry/data |  | ||||||
|  | |||||||
| @ -1,11 +1,13 @@ | |||||||
| language: node_js | language: node_js | ||||||
| services: | services: | ||||||
|   - couchdb |  | ||||||
|   - docker |   - docker | ||||||
| notifications: | notifications: | ||||||
|   email: false |   email: false | ||||||
| node_js: | node_js: | ||||||
|  |   - 9 | ||||||
|   - 8 |   - 8 | ||||||
|  | os: | ||||||
|  |   - linux | ||||||
| 
 | 
 | ||||||
| # Trigger a push build on caribou and greenkeeper branches + PRs build on every branches | # Trigger a push build on caribou and greenkeeper branches + PRs build on every branches | ||||||
| # Avoid double build on PRs (See https://github.com/travis-ci/travis-ci/issues/1147) | # Avoid double build on PRs (See https://github.com/travis-ci/travis-ci/issues/1147) | ||||||
|  | |||||||
| @ -46,11 +46,12 @@ | |||||||
|     "eslint-plugin-prettier": "^2.3.0", |     "eslint-plugin-prettier": "^2.3.0", | ||||||
|     "file-url": "^2.0.2", |     "file-url": "^2.0.2", | ||||||
|     "fs-extra": "^4.0.2", |     "fs-extra": "^4.0.2", | ||||||
|  |     "got": "^8.0.0", | ||||||
|     "js-yaml": "^3.10.0", |     "js-yaml": "^3.10.0", | ||||||
|     "mockserver-client": "^2.0.0", |     "mockserver-client": "^2.0.0", | ||||||
|     "nock": "^9.0.2", |     "nock": "^9.0.2", | ||||||
|     "npm-registry-couchapp": "^2.6.12", |  | ||||||
|     "nyc": "^11.2.1", |     "nyc": "^11.2.1", | ||||||
|  |     "p-retry": "^1.0.0", | ||||||
|     "prettier": "~1.8.0", |     "prettier": "~1.8.0", | ||||||
|     "proxyquire": "^1.8.0", |     "proxyquire": "^1.8.0", | ||||||
|     "sinon": "^4.0.0", |     "sinon": "^4.0.0", | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| import Docker from 'dockerode'; | import Docker from 'dockerode'; | ||||||
| import getStream from 'get-stream'; | import getStream from 'get-stream'; | ||||||
|  | import got from 'got'; | ||||||
|  | import pRetry from 'p-retry'; | ||||||
| import {mockServerClient} from 'mockserver-client'; | import {mockServerClient} from 'mockserver-client'; | ||||||
| 
 | 
 | ||||||
| const MOCK_SERVER_PORT = 1080; | const MOCK_SERVER_PORT = 1080; | ||||||
| @ -7,6 +9,14 @@ const MOCK_SERVER_HOST = 'localhost'; | |||||||
| const docker = new Docker(); | const docker = new Docker(); | ||||||
| let container; | let container; | ||||||
| 
 | 
 | ||||||
|  | async function checkStatus() { | ||||||
|  |   const response = await got.put(`http://${MOCK_SERVER_HOST}:${MOCK_SERVER_PORT}/status`, {cache: false}); | ||||||
|  |   if (response.status === 200) { | ||||||
|  |     // If the registry returns a 200 status, it's ready. Abort the retry.
 | ||||||
|  |     throw new pRetry.AbortError(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Download the `mockserver` Docker image, create a new container and start it. |  * Download the `mockserver` Docker image, create a new container and start it. | ||||||
|  * |  * | ||||||
| @ -19,7 +29,14 @@ async function start() { | |||||||
|     Image: 'jamesdbloom/mockserver', |     Image: 'jamesdbloom/mockserver', | ||||||
|     PortBindings: {[`${MOCK_SERVER_PORT}/tcp`]: [{HostPort: `${MOCK_SERVER_PORT}`}]}, |     PortBindings: {[`${MOCK_SERVER_PORT}/tcp`]: [{HostPort: `${MOCK_SERVER_PORT}`}]}, | ||||||
|   }); |   }); | ||||||
|   return container.start(); |   await container.start(); | ||||||
|  | 
 | ||||||
|  |   try { | ||||||
|  |     // Wait for the mock server to be ready
 | ||||||
|  |     await pRetry(checkStatus, {retries: 5, minTimeout: 1000, factor: 2}); | ||||||
|  |   } catch (err) { | ||||||
|  |     throw new Error(`Couldn't start mock-server after 30s`); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
							
								
								
									
										69
									
								
								test/helpers/npm-registry.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								test/helpers/npm-registry.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | import Docker from 'dockerode'; | ||||||
|  | import getStream from 'get-stream'; | ||||||
|  | import got from 'got'; | ||||||
|  | import pRetry from 'p-retry'; | ||||||
|  | 
 | ||||||
|  | const SERVER_PORT = 15986; | ||||||
|  | const COUCHDB_PORT = 5984; | ||||||
|  | const SERVER_HOST = 'localhost'; | ||||||
|  | const NPM_USERNAME = 'integration'; | ||||||
|  | const NPM_PASSWORD = 'suchsecure'; | ||||||
|  | const NPM_EMAIL = 'integration@test.com'; | ||||||
|  | const docker = new Docker(); | ||||||
|  | let container; | ||||||
|  | 
 | ||||||
|  | async function checkStatus() { | ||||||
|  |   const response = await got(`http://${SERVER_HOST}:${SERVER_PORT}/registry/_design/app`, {cache: false}); | ||||||
|  |   if (response.status === 200) { | ||||||
|  |     // If the registry returns a 200 status, it's ready. Abort the retry.
 | ||||||
|  |     throw new pRetry.AbortError(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | async function start() { | ||||||
|  |   await getStream(await docker.pull('npmjs/npm-docker-couchdb:1.6.1')); | ||||||
|  | 
 | ||||||
|  |   container = await docker.createContainer({ | ||||||
|  |     Image: 'npmjs/npm-docker-couchdb:1.6.1', | ||||||
|  |     PortBindings: {[`${COUCHDB_PORT}/tcp`]: [{HostPort: `${SERVER_PORT}`}]}, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   await container.start(); | ||||||
|  | 
 | ||||||
|  |   try { | ||||||
|  |     // Wait for the registry to be ready
 | ||||||
|  |     await pRetry(checkStatus, {retries: 5, minTimeout: 1000, factor: 2}); | ||||||
|  |   } catch (err) { | ||||||
|  |     throw new Error(`Couldn't start npm-docker-couchdb after 30s`); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Create user
 | ||||||
|  |   await got(`http://${SERVER_HOST}:${SERVER_PORT}/_users/org.couchdb.user:${NPM_USERNAME}`, { | ||||||
|  |     json: true, | ||||||
|  |     auth: 'admin:admin', | ||||||
|  |     method: 'PUT', | ||||||
|  |     body: { | ||||||
|  |       _id: `org.couchdb.user:${NPM_USERNAME}`, | ||||||
|  |       name: NPM_USERNAME, | ||||||
|  |       roles: [], | ||||||
|  |       type: 'user', | ||||||
|  |       password: NPM_PASSWORD, | ||||||
|  |       email: NPM_EMAIL, | ||||||
|  |     }, | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const url = `http://${SERVER_HOST}:${SERVER_PORT}/registry/_design/app/_rewrite/`; | ||||||
|  | 
 | ||||||
|  | const authEnv = { | ||||||
|  |   npm_config_registry: url, // eslint-disable-line camelcase
 | ||||||
|  |   NPM_USERNAME, | ||||||
|  |   NPM_PASSWORD, | ||||||
|  |   NPM_EMAIL, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | async function stop() { | ||||||
|  |   return container.stop(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default {start, stop, authEnv, url}; | ||||||
| @ -1,14 +0,0 @@ | |||||||
| import execa from 'execa'; |  | ||||||
| 
 |  | ||||||
| const opts = {cwd: __dirname}; |  | ||||||
| const uri = 'http://localhost:' + (process.env.TRAVIS === 'true' ? 5984 : 15986) + '/registry/_design/app/_rewrite/'; |  | ||||||
| 
 |  | ||||||
| function start() { |  | ||||||
|   return execa('./start.sh', opts); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function stop() { |  | ||||||
|   return execa('./stop.sh', opts); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export default {start, stop, uri}; |  | ||||||
| @ -1,20 +0,0 @@ | |||||||
| [couchdb] |  | ||||||
| database_dir = data |  | ||||||
| view_index_dir = data |  | ||||||
| delayed_commits = false |  | ||||||
| uuid = bf4ecd84a7c89d60b5b2540fdf8c322c |  | ||||||
| 
 |  | ||||||
| [couch_httpd_auth] |  | ||||||
| public_fields = appdotnet, avatar, avatarMedium, avatarLarge, date, email, fields, freenode, fullname, github, homepage, name, roles, twitter, type, _id, _rev |  | ||||||
| users_db_public = true |  | ||||||
| 
 |  | ||||||
| [httpd] |  | ||||||
| port = 15986 |  | ||||||
| bind_address = 127.0.0.1 |  | ||||||
| secure_rewrites = false |  | ||||||
| 
 |  | ||||||
| [log] |  | ||||||
| file = couch/couch.log |  | ||||||
| 
 |  | ||||||
| [admins] |  | ||||||
| admin = -pbkdf2-89582b49cd2e8443e29a841f5a76d367956a8e58,1afa2f1531a17ac97f2ac9e334293753,10 |  | ||||||
| @ -1,41 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| # exit if an error occurs |  | ||||||
| set -e |  | ||||||
| 
 |  | ||||||
| cd $(dirname $0) |  | ||||||
| 
 |  | ||||||
| mkdir -p couch |  | ||||||
| 
 |  | ||||||
| if [[ $TRAVIS = true ]] |  | ||||||
| then |  | ||||||
|   COUCH=http://admin:password@127.0.0.1:5984 |  | ||||||
| 
 |  | ||||||
|   curl -X PUT http://127.0.0.1:5984/_config/admins/admin -d '"password"' |  | ||||||
| 
 |  | ||||||
|   curl -X PUT $COUCH/_config/couchdb/delayed_commits -d '"false"' |  | ||||||
|   curl -X PUT $COUCH/_config/couch_httpd_auth/users_db_public -d '"true"' |  | ||||||
|   curl -X PUT $COUCH/_config/couch_httpd_auth/public_fields -d '"appdotnet, avatar, avatarMedium, avatarLarge, date, email, fields, freenode, fullname, github, homepage, name, roles, twitter, type, _id, _rev"' |  | ||||||
|   curl -X PUT $COUCH/_config/httpd/secure_rewrites -d '"false"' |  | ||||||
| 
 |  | ||||||
| else |  | ||||||
|   COUCH=http://admin:password@127.0.0.1:15986 |  | ||||||
|   couchdb -b -a local.ini -p couch/pid -o couch/stdout.log -e couch/stderr.log |  | ||||||
|   # wait for couch to start |  | ||||||
|   sleep 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # create "registry" database |  | ||||||
| curl -X PUT $COUCH/registry |  | ||||||
| 
 |  | ||||||
| # create sample npm user |  | ||||||
| curl -X PUT $COUCH/_users/org.couchdb.user:integration -H Content-Type:application/json --data-binary '{"_id": "org.couchdb.user:integration", "name": "integration", "roles": [], "type": "user", "password": "suchsecure", "email": "integration@test.com"}' |  | ||||||
| 
 |  | ||||||
| # npm-registry-couchpp needs this variable set to run |  | ||||||
| export DEPLOY_VERSION=nope |  | ||||||
| 
 |  | ||||||
| # setup npm-registry-couchapp |  | ||||||
| npm explore npm-registry-couchapp -- npm start --npm-registry-couchapp:couch=$COUCH/registry |  | ||||||
| npm explore npm-registry-couchapp -- npm run load --npm-registry-couchapp:couch=$COUCH/registry |  | ||||||
| export NO_PROMPT=yes |  | ||||||
| npm explore npm-registry-couchapp -- npm run copy --npm-registry-couchapp:couch=$COUCH/registry |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| # close couchdb background process |  | ||||||
| couchdb -d |  | ||||||
| 
 |  | ||||||
| # delete data and logs |  | ||||||
| cd $(dirname $0) |  | ||||||
| 
 |  | ||||||
| cat couch/{couch,stdout,stderr}.log |  | ||||||
| 
 |  | ||||||
| cat couch/pid | xargs kill |  | ||||||
| rm -rf couch |  | ||||||
| rm -rf data |  | ||||||
| @ -3,15 +3,15 @@ import {writeJson, readJson} from 'fs-extra'; | |||||||
| import {stub} from 'sinon'; | import {stub} from 'sinon'; | ||||||
| import execa from 'execa'; | import execa from 'execa'; | ||||||
| import {gitRepo, gitCommits, gitHead, gitTagVersion, gitPackRefs, gitAmmendCommit} from './helpers/git-utils'; | import {gitRepo, gitCommits, gitHead, gitTagVersion, gitPackRefs, gitAmmendCommit} from './helpers/git-utils'; | ||||||
| import registry from './helpers/registry'; |  | ||||||
| import mockServer from './helpers/mockserver'; | import mockServer from './helpers/mockserver'; | ||||||
|  | import npmRegistry from './helpers/npm-registry'; | ||||||
| import semanticRelease from '..'; | import semanticRelease from '..'; | ||||||
| 
 | 
 | ||||||
| /* eslint camelcase: ["error", {properties: "never"}] */ | /* eslint camelcase: ["error", {properties: "never"}] */ | ||||||
| 
 | 
 | ||||||
| // Environment variables used with cli
 | // Environment variables used with cli
 | ||||||
| const env = { | const env = { | ||||||
|   npm_config_registry: registry.uri, |   npm_config_registry: npmRegistry.url, | ||||||
|   GH_TOKEN: 'github_token', |   GH_TOKEN: 'github_token', | ||||||
|   GITHUB_URL: mockServer.url, |   GITHUB_URL: mockServer.url, | ||||||
|   NPM_EMAIL: 'integration@test.com', |   NPM_EMAIL: 'integration@test.com', | ||||||
| @ -23,10 +23,10 @@ const pluginError = require.resolve('./fixtures/plugin-error'); | |||||||
| const pluginInheritedError = require.resolve('./fixtures/plugin-error-inherited'); | const pluginInheritedError = require.resolve('./fixtures/plugin-error-inherited'); | ||||||
| 
 | 
 | ||||||
| test.before(async () => { | test.before(async () => { | ||||||
|  |   // Start the local NPM registry
 | ||||||
|  |   await npmRegistry.start(); | ||||||
|   // Start Mock Server
 |   // Start Mock Server
 | ||||||
|   await mockServer.start(); |   await mockServer.start(); | ||||||
|   // Start the local NPM registry
 |  | ||||||
|   await registry.start(); |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test.beforeEach(t => { | test.beforeEach(t => { | ||||||
| @ -54,9 +54,10 @@ test.afterEach.always(t => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test.after.always(async () => { | test.after.always(async () => { | ||||||
|   await mockServer.stop(); |  | ||||||
|   // Stop the local NPM registry
 |   // Stop the local NPM registry
 | ||||||
|   await registry.stop(); |   await npmRegistry.stop(); | ||||||
|  |   // Stop Mock Server
 | ||||||
|  |   await mockServer.stop(); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test.serial('Release patch, minor and major versions', async t => { | test.serial('Release patch, minor and major versions', async t => { | ||||||
| @ -71,7 +72,7 @@ test.serial('Release patch, minor and major versions', async t => { | |||||||
|     version: '0.0.0-dev', |     version: '0.0.0-dev', | ||||||
|     repository: {url: `git+https://github.com/${owner}/${packageName}`}, |     repository: {url: `git+https://github.com/${owner}/${packageName}`}, | ||||||
|     release: {verifyConditions: ['@semantic-release/github', '@semantic-release/npm']}, |     release: {verifyConditions: ['@semantic-release/github', '@semantic-release/npm']}, | ||||||
|     publishConfig: {registry: registry.uri}, |     publishConfig: {registry: npmRegistry.url}, | ||||||
|   }); |   }); | ||||||
|   // Create a npm-shrinkwrap.json file
 |   // Create a npm-shrinkwrap.json file
 | ||||||
|   await execa('npm', ['shrinkwrap'], {env}); |   await execa('npm', ['shrinkwrap'], {env}); | ||||||
| @ -284,7 +285,7 @@ test.serial('Release versions from a packed git repository, using tags to determ | |||||||
|     version: '0.0.0-dev', |     version: '0.0.0-dev', | ||||||
|     repository: {url: `git@github.com:${owner}/${packageName}.git`}, |     repository: {url: `git@github.com:${owner}/${packageName}.git`}, | ||||||
|     release: {verifyConditions: ['@semantic-release/github', '@semantic-release/npm']}, |     release: {verifyConditions: ['@semantic-release/github', '@semantic-release/npm']}, | ||||||
|     publishConfig: {registry: registry.uri}, |     publishConfig: {registry: npmRegistry.url}, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   /* Initial release */ |   /* Initial release */ | ||||||
| @ -399,7 +400,7 @@ test.serial('Create a tag as a recovery solution for "ENOTINHISTORY" error', asy | |||||||
|     version: '0.0.0-dev', |     version: '0.0.0-dev', | ||||||
|     repository: {url: `git+https://github.com/${owner}/${packageName}`}, |     repository: {url: `git+https://github.com/${owner}/${packageName}`}, | ||||||
|     release: {verifyConditions: ['@semantic-release/github', '@semantic-release/npm']}, |     release: {verifyConditions: ['@semantic-release/github', '@semantic-release/npm']}, | ||||||
|     publishConfig: {registry: registry.uri}, |     publishConfig: {registry: npmRegistry.url}, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   /* Initial release */ |   /* Initial release */ | ||||||
| @ -528,7 +529,7 @@ test.serial('Dry-run', async t => { | |||||||
|     name: packageName, |     name: packageName, | ||||||
|     version: '0.0.0-dev', |     version: '0.0.0-dev', | ||||||
|     repository: {url: `git+https://github.com/${owner}/${packageName}`}, |     repository: {url: `git+https://github.com/${owner}/${packageName}`}, | ||||||
|     publishConfig: {registry: registry.uri}, |     publishConfig: {registry: npmRegistry.url}, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   /* Initial release */ |   /* Initial release */ | ||||||
| @ -557,7 +558,7 @@ test.serial('Pass options via CLI arguments', async t => { | |||||||
|     name: packageName, |     name: packageName, | ||||||
|     version: '0.0.0-dev', |     version: '0.0.0-dev', | ||||||
|     repository: {url: `git+https://github.com/${owner}/${packageName}`}, |     repository: {url: `git+https://github.com/${owner}/${packageName}`}, | ||||||
|     publishConfig: {registry: registry.uri}, |     publishConfig: {registry: npmRegistry.url}, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   /* Initial release */ |   /* Initial release */ | ||||||
| @ -597,7 +598,7 @@ test.serial('Run via JS API', async t => { | |||||||
|     name: packageName, |     name: packageName, | ||||||
|     version: '0.0.0-dev', |     version: '0.0.0-dev', | ||||||
|     repository: {url: `git+https://github.com/${owner}/${packageName}`}, |     repository: {url: `git+https://github.com/${owner}/${packageName}`}, | ||||||
|     publishConfig: {registry: registry.uri}, |     publishConfig: {registry: npmRegistry.url}, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   /* Initial release */ |   /* Initial release */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user