diff --git a/tasks/admin/create-components.js b/tasks/admin/components/create.js similarity index 98% rename from tasks/admin/create-components.js rename to tasks/admin/components/create.js index 688ff3eb8..c8ca9f0d8 100644 --- a/tasks/admin/create-components.js +++ b/tasks/admin/components/create.js @@ -37,7 +37,6 @@ var // config config = require('../config/user'), - github = require('../config/admin/github'), release = require('../config/admin/release'), project = require('../config/project/release'), @@ -70,7 +69,7 @@ module.exports = function(callback) { isCSS = fs.existsSync(output.compressed + component + '.css'), capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1), packageName = release.packageRoot + component, - repoName = release.repoRoot + capitalizedComponent, + repoName = release.componentRepoRoot + capitalizedComponent, gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git', repoURL = 'https://github.com/' + release.org + '/' + repoName + '/', regExp = { diff --git a/tasks/admin/init-components.js b/tasks/admin/components/init.js similarity index 84% rename from tasks/admin/init-components.js rename to tasks/admin/components/init.js index f12d3e36a..eca6ad89d 100644 --- a/tasks/admin/init-components.js +++ b/tasks/admin/components/init.js @@ -13,25 +13,25 @@ */ var - gulp = require('gulp'), + gulp = require('gulp'), // node dependencies - console = require('better-console'), - del = require('del'), - fs = require('fs'), - path = require('path'), - git = require('gulp-git'), - githubAPI = require('github'), - mkdirp = require('mkdirp'), + console = require('better-console'), + del = require('del'), + fs = require('fs'), + path = require('path'), + git = require('gulp-git'), + githubAPI = require('github'), + mkdirp = require('mkdirp'), // admin files - github = require('../config/admin/github.js'), - release = require('../config/admin/release'), - project = require('../config/project/release'), + github = require('../config/admin/github.js'), + release = require('../config/admin/release'), + project = require('../config/project/release'), // oAuth configuration for GitHub - oAuth = fs.existsSync(__dirname + '/../config/admin/oauth.js') + oAuth = fs.existsSync(__dirname + '/../config/admin/oauth.js') ? require('../config/admin/oauth') : false, @@ -68,7 +68,7 @@ module.exports = function(callback) { component = release.components[index] outputDirectory = path.resolve(release.outputRoot + component), capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1), - repoName = release.repoRoot + capitalizedComponent, + repoName = release.componentRepoRoot + capitalizedComponent, gitOptions = { cwd: outputDirectory }, pullOptions = { args: '-q', cwd: outputDirectory, quiet: true }, @@ -87,7 +87,7 @@ module.exports = function(callback) { } // clean folder - if(release.outputRoot.search('../components') == 0) { + if(release.outputRoot.search('../repos') == 0) { console.info('Cleaning dir', outputDirectory); del.sync([outputDirectory + '**/*'], {silent: true, force: true}); } diff --git a/tasks/admin/update-components.js b/tasks/admin/components/update.js similarity index 96% rename from tasks/admin/update-components.js rename to tasks/admin/components/update.js index 914b8a4fc..1a69900a4 100644 --- a/tasks/admin/update-components.js +++ b/tasks/admin/components/update.js @@ -35,7 +35,7 @@ var : false, // shorthand - version = project.version + version = project.version ; module.exports = function() { @@ -65,7 +65,7 @@ module.exports = function() { component = release.components[index] outputDirectory = path.resolve(release.outputRoot + component), capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1), - repoName = release.repoRoot + capitalizedComponent, + repoName = release.componentRepoRoot + capitalizedComponent, gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git', repoURL = 'https://github.com/' + release.org + '/' + repoName + '/', @@ -82,7 +82,7 @@ module.exports = function() { commitMessage = (isNewVersion) ? 'Updated component to version ' + version - : 'Updated automatically main repository', + : 'Updated files from main repo', gitOptions = { cwd: outputDirectory }, commitOptions = { args: commitArgs, cwd: outputDirectory }, diff --git a/tasks/admin/distributions/create.js b/tasks/admin/distributions/create.js new file mode 100644 index 000000000..ccd1b8f6d --- /dev/null +++ b/tasks/admin/distributions/create.js @@ -0,0 +1,109 @@ +/******************************* + Create Distributions +*******************************/ + +/* + This will create individual distribution repositories for each SUI distribution + + * copy distribution files to release + * update package.json file +*/ + +var + gulp = require('gulp'), + + // node dependencies + console = require('better-console'), + del = require('del'), + fs = require('fs'), + path = require('path'), + runSequence = require('run-sequence'), + + // admin dependencies + concatFileNames = require('gulp-concat-filenames'), + debug = require('gulp-debug'), + flatten = require('gulp-flatten'), + git = require('gulp-git'), + jsonEditor = require('gulp-json-editor'), + plumber = require('gulp-plumber'), + rename = require('gulp-rename'), + replace = require('gulp-replace'), + tap = require('gulp-tap'), + + // config + config = require('../config/user'), + release = require('../config/admin/release'), + project = require('../config/project/release'), + + // shorthand + version = project.version, + output = config.paths.output + +; + + +module.exports = function(callback) { + var + stream, + index, + tasks = [] + ; + + for(index in release.distributions) { + + var + distribution = release.distributions[index] + ; + + // streams... designed to save time and make coding fun... + (function(distribution) { + + var + outputDirectory = release.outputRoot + distribution, + repoName = release.distRepoRoot + distribution + task = { + repo : distribution + ' create repo', + package : distribution + ' create package.json' + } + ; + + // copy files into output folder adjusting asset paths + gulp.task(task.repo, false, function() { + return gulp.src(release.source + distribution + '.*') + .pipe(plumber()) + .pipe(flatten()) + .pipe(replace(release.paths.source, release.paths.output)) + .pipe(gulp.dest(outputDirectory)) + ; + }); + + // extend package.json + gulp.task(task.package, false, function() { + return gulp.src(zzzzzzzzzzzzz) + .pipe(plumber()) + .pipe(flatten()) + .pipe(jsonEditor(function(package) { + if(version) { + package.version = version; + } + return package; + })) + .pipe(gulp.dest(outputDirectory)) + ; + }); + + // synchronous tasks in orchestrator? I think not + gulp.task(task.all, false, function(callback) { + runSequence([ + task.repo, + task.package + ], callback); + }); + + tasks.push(task.all); + + })(distribution); + } + + runSequence(tasks, callback); +}; \ No newline at end of file diff --git a/tasks/admin/distributions/init.js b/tasks/admin/distributions/init.js new file mode 100644 index 000000000..4059cb891 --- /dev/null +++ b/tasks/admin/distributions/init.js @@ -0,0 +1,170 @@ +/******************************* + Init Dist Repos +*******************************/ + +/* + + This task pulls the latest version of distribution from GitHub + + * Creates new repo if doesnt exist (locally & GitHub) + * Adds remote it doesnt exists + * Pulls latest changes from repo + +*/ + +var + gulp = require('gulp'), + + // node dependencies + console = require('better-console'), + del = require('del'), + fs = require('fs'), + path = require('path'), + git = require('gulp-git'), + githubAPI = require('github'), + mkdirp = require('mkdirp'), + + // admin files + github = require('../config/admin/github.js'), + release = require('../config/admin/release'), + project = require('../config/project/release'), + + + // oAuth configuration for GitHub + oAuth = fs.existsSync(__dirname + '/../config/admin/oauth.js') + ? require('../config/admin/oauth') + : false, + + // shorthand + version = project.version +; + +module.exports = function(callback) { + + var + index = -1, + total = release.components.length, + timer, + stream, + stepRepo + ; + + if(!oAuth) { + console.error('Must add oauth token for GitHub in tasks/config/admin/oauth.js'); + return; + } + + // Do Git commands synchronously per component, to avoid issues + stepRepo = function() { + + index = index + 1; + + if(index >= total) { + callback(); + return; + } + + var + component = release.components[index] + outputDirectory = path.resolve(release.outputRoot + component), + capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1), + repoName = release.distRepoRoot + capitalizedComponent, + + gitOptions = { cwd: outputDirectory }, + pullOptions = { args: '-q', cwd: outputDirectory, quiet: true }, + resetOptions = { args: '-q --hard', cwd: outputDirectory, quiet: true }, + + gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git', + repoURL = 'https://github.com/' + release.org + '/' + repoName + '/', + localRepoSetup = fs.existsSync(path.join(outputDirectory, '.git')) + ; + + console.log('Processing repository: ' + outputDirectory); + + // create folder if doesn't exist + if( !fs.existsSync(outputDirectory) ) { + mkdirp.sync(outputDirectory); + } + + // clean folder + if(release.outputRoot.search('../repos') == 0) { + console.info('Cleaning dir', outputDirectory); + del.sync([outputDirectory + '**/*'], {silent: true, force: true}); + } + + // set-up local repo + function setupRepo() { + if(localRepoSetup) { + addRemote(); + } + else { + initRepo(); + } + } + + function initRepo() { + console.info('Initializing repository for ' + component); + git.init(gitOptions, function(error) { + if(error) { + console.error('Error initializing repo', error); + } + addRemote(); + }); + } + + function createRepo() { + console.info('Creating GitHub repo ' + repoURL); + github.repos.createFromOrg({ + org : release.org, + name : repoName, + homepage : release.homepage + }, function() { + setupRepo(); + }); + } + + function addRemote() { + console.info('Adding remote origin as ' + gitURL); + git.addRemote('origin', gitURL, gitOptions, function(){ + pullFiles(); + }); + } + + function pullFiles() { + console.info('Pulling ' + component + ' files'); + git.pull('origin', 'master', pullOptions, function(error) { + resetFiles(); + }); + } + + function resetFiles() { + console.info('Resetting files to head'); + git.reset('HEAD', resetOptions, function(error) { + nextRepo(); + }); + } + + function nextRepo() { + //console.log('Sleeping for 1 second...'); + // avoid rate throttling + global.clearTimeout(timer); + timer = global.setTimeout(function() { + stepRepo() + }, 0); + } + + + if(localRepoSetup) { + pullFiles(); + } + else { + setupRepo(); + // createRepo() only use to create remote repo (easier to do manually) + } + + }; + + stepRepo(); + + +}; diff --git a/tasks/admin/distributions/update.js b/tasks/admin/distributions/update.js new file mode 100644 index 000000000..e20ccf5b7 --- /dev/null +++ b/tasks/admin/distributions/update.js @@ -0,0 +1,177 @@ +/******************************* + Update Repos +*******************************/ + +/* + + This task update all SUI individual component repos with new versions of components + + * Commits changes from create repo + * Pushes changes to GitHub + * Tag new releases if version changed in main repo + +*/ + +var + gulp = require('gulp'), + + // node dependencies + console = require('better-console'), + fs = require('fs'), + path = require('path'), + git = require('gulp-git'), + githubAPI = require('github'), + requireDotFile = require('require-dot-file'), + + // admin files + github = require('../config/admin/github.js'), + release = require('../config/admin/release'), + project = require('../config/project/release'), + + + // oAuth configuration for GitHub + oAuth = fs.existsSync(__dirname + '/../config/admin/oauth.js') + ? require('../config/admin/oauth') + : false, + + // shorthand + version = project.version +; + +module.exports = function() { + + var + index = -1, + total = release.components.length, + timer, + stream, + stepRepo + ; + + if(!oAuth) { + console.error('Must add oauth token for GitHub in tasks/config/admin/oauth.js'); + return; + } + + // Do Git commands synchronously per component, to avoid issues + stepRepo = function() { + + index = index + 1; + if(index >= total) { + return; + } + + var + component = release.components[index] + outputDirectory = path.resolve(release.outputRoot + component), + capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1), + repoName = release.distRepoRoot + capitalizedComponent, + + gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git', + repoURL = 'https://github.com/' + release.org + '/' + repoName + '/', + + commitArgs = (oAuth.name !== undefined && oAuth.email !== undefined) + ? '--author "' + oAuth.name + ' <' + oAuth.email + '>"' + : '', + + componentPackage = fs.existsSync(outputDirectory + 'package.json' ) + ? require(outputDirectory + 'package.json') + : false, + + isNewVersion = (version && componentPackage.version != version), + + commitMessage = (isNewVersion) + ? 'Updated component to version ' + version + : 'Updated files from main repo', + + gitOptions = { cwd: outputDirectory }, + commitOptions = { args: commitArgs, cwd: outputDirectory }, + releaseOptions = { tag_name: version, owner: release.org, repo: repoName }, + usernameOptions = { args : 'config user.name "' + oAuth.name + '"', cwd: outputDirectory }, + emailOptions = { args : 'config user.email "' + oAuth.email + '"', cwd: outputDirectory }, + + localRepoSetup = fs.existsSync(path.join(outputDirectory, '.git')), + canProceed = true + ; + + + console.info('Processing repository:' + outputDirectory); + + function setUser() { + git.exec(usernameOptions, function () { + git.exec(emailOptions, function () { + commitFiles(); + }); + }); + } + + // standard path + function commitFiles() { + // commit files + console.info('Committing ' + component + ' files', commitArgs); + gulp.src('**/*', gitOptions) + .pipe(git.add(gitOptions)) + .pipe(git.commit(commitMessage, commitOptions)) + .on('error', function(error) { + // canProceed = false; bug in git commit + }) + .on('finish', function(callback) { + if(canProceed) { + pushFiles(); + } + else { + console.info('Nothing new to commit'); + nextRepo(); + } + }) + ; + } + + // push changess to remote + function pushFiles() { + console.info('Pushing files for ' + component); + git.push('origin', 'master', { args: '-f', cwd: outputDirectory }, function(error) { + console.info('Push completed successfully'); + createRelease(); + }); + } + + // create release on GitHub.com + function createRelease() { + console.log('Tagging release as ', version); + github.releases.createRelease(releaseOptions, function() { + nextRepo(); + tagFiles(); + }); + tagFiles(); + } + + // Tags files locally + function tagFiles() { + console.info('Tagging new version ' + component, version); + git.tag(version, 'Updated version from semantic-ui (automatic)', function (err) { + nextRepo(); + }); + } + + // Steps to next repository + function nextRepo() { + console.log('Sleeping for 1 second...'); + // avoid rate throttling + global.clearTimeout(timer); + return stepRepo() + } + + + if(localRepoSetup) { + commitFiles(); + } + else { + console.error('Repository must be setup before running update components'); + } + + }; + + stepRepo(); + +}; diff --git a/tasks/admin/register-repos.js b/tasks/admin/register-repos.js deleted file mode 100644 index 70f4411e3..000000000 --- a/tasks/admin/register-repos.js +++ /dev/null @@ -1,64 +0,0 @@ -/******************************* - Register PM -*******************************/ - -/* - Task to register component repos with Package Managers - * Registers component with bower - * Registers component with NPM -*/ - -var - // node dependencies - process = require('child_process'), - - // config - release = require('../config/admin/release'), - - total = release.components.length, - index = -1, - stream, - stepRepo -; - -module.exports = function(callback) { - - console.log('Registering repos with package managers'); - - // Do Git commands synchronously per component, to avoid issues - stepRepo = function() { - index = index + 1; - if(index >= total) { - return; - } - var - component = release.components[index], - outputDirectory = release.outputRoot + component + '/', - capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1), - packageName = release.packageRoot + component, - repoName = release.repoRoot + capitalizedComponent, - gitURL = 'https://github.com/' + release.org + '/' + repoName + '.git', - exec = process.exec, - execSettings = {cwd: outputDirectory}, - registerBower = 'bower register ' + packageName + ' ' + gitURL, - updateNPM = 'npm publish' - - ; - - /* Register with Bower */ - /* One Time - exec(registerBower, execSettings, function(err, stdout, stderr) { - stepRepo(); - }); - */ - - /* Register with NPM */ - exec(updateNPM, execSettings, function(err, stdout, stderr) { - console.log(err, stdout, stderr); - stepRepo(); - }); - - }; - stepRepo(); -}; - diff --git a/tasks/admin/release-all.js b/tasks/admin/release-all.js index dbf490211..20df1f9dd 100644 --- a/tasks/admin/release-all.js +++ b/tasks/admin/release-all.js @@ -5,8 +5,10 @@ /* This task update all SUI individual component repos with new versions of components + * Initializes repositories with current versions * Creates local files at ../components/ with each repo for release - * Syncs each component with GitHub + * Commits changes from create components + * Registers new versions with NPM Publish */ @@ -18,11 +20,10 @@ var module.exports = function() { runSequence( - //'build', // build Semantic - 'init components', // create each component repo - 'create components', // create each component repo - 'update components', // update component repos on github - 'register repos' + 'build', // build Semantic + 'init components', // sync with current github version + 'create components', // update each repo + 'update components' // commit changes to github ); }; \ No newline at end of file diff --git a/tasks/admin/release.js b/tasks/admin/release.js index 8eab72db7..c8c91581f 100644 --- a/tasks/admin/release.js +++ b/tasks/admin/release.js @@ -1,9 +1,14 @@ /******************************* - Release + Release *******************************/ /* - This task update only SUI repos that use the full release (all components) + This task update all SUI individual component repos with new versions of components + + * Initializes repositories with current versions + * Creates local files at ../distributions/ with each repo for release + * Commits changes from create components + * Registers new versions with NPM Publish */ @@ -11,11 +16,14 @@ var runSequence = require('run-sequence') ; +/* Release All */ module.exports = function() { runSequence( - 'build', // build semantic - 'create static repo' // create standalone css repo + //'build', // build Semantic + 'init distributions' // sync with current github version + //'create distributions', // update each repo with changes from master repo + //'update distributions' // commit changes to github ); }; \ No newline at end of file diff --git a/tasks/collections/admin.js b/tasks/collections/admin.js index 4b476a453..21fe420f1 100644 --- a/tasks/collections/admin.js +++ b/tasks/collections/admin.js @@ -16,25 +16,35 @@ module.exports = function(gulp) { var + // less/css distributions + initComponents = require('../admin/components/init'), + createComponents = require('../admin/components/create'), + updateComponents = require('../admin/components/update'), + // single component releases - initComponents = require('../admin/init-components'), - createComponents = require('../admin/create-components'), - updateComponents = require('../admin/update-components'), + initDistributions = require('../admin/distributions/init'), + createDistributions = require('../admin/distributions/create'), + updateDistributions = require('../admin/distributions/update'), // one time register with PM - registerRepos = require('../admin/register-repos'), + registerRepos = require('../admin/register-repos'), // meta tasks - releaseAll = require('../admin/release-all'), - release = require('../admin/release') + releaseAll = require('../admin/release-all'), + release = require('../admin/release') ; + gulp.task('release', 'Publishes only packaged releases', release); + gulp.task('release all', 'Publishes all releases (components, package)', releaseAll); + + gulp.task('init distributions', 'Grabs each component from GitHub', initDistributions); + gulp.task('create distributions', 'Updates files in each repo', createDistributions); + gulp.task('update distributions', 'Commits component updates from create to GitHub', updateDistributions); + gulp.task('init components', 'Grabs each component from GitHub', initComponents); gulp.task('create components', 'Updates files in each repo', createComponents); gulp.task('update components', 'Commits component updates from create to GitHub', updateComponents); - gulp.task('register repos', 'Registers packages with Bower and NPM', registerRepos); - gulp.task('release all', 'Publishes all releases (components, package)', releaseAll); - gulp.task('release', 'Publishes only packaged releases', release); + gulp.task('register repos', 'Registers all packages with NPM', registerRepos); }; \ No newline at end of file diff --git a/tasks/config/admin/release.js b/tasks/config/admin/release.js index 435b08817..43b93e37e 100644 --- a/tasks/config/admin/release.js +++ b/tasks/config/admin/release.js @@ -34,15 +34,26 @@ module.exports = { meteor : 'package.js' }, - // root name for repos - repoRoot : 'UI-', - packageRoot : 'semantic-ui-', + // root name for distribution repos + distRepoRoot : 'Semantic-UI-', + + // root name for single component repos + componentRepoRoot : 'UI-', + + // root name for package managers + packageRoot : 'semantic-ui-', // root path to repos - outputRoot : '../components/', + outputRoot : '../repos/', homepage : 'http://www.semantic-ui.com', + // distributions that get separate repos + distributions: [ + 'LESS', + 'CSS' + ], + // components that get separate repositories for bower/npm components : [ 'accordion',