diff --git a/resource/history/mage-os/product-community-edition/1.0.0.json b/resource/history/mage-os/product-community-edition/1.0.0.json index e9f3781..243ec0e 100644 --- a/resource/history/mage-os/product-community-edition/1.0.0.json +++ b/resource/history/mage-os/product-community-edition/1.0.0.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.0", "mage-os/inventory-metapackage": "1.0.0", "mage-os/page-builder": "1.0.0" + }, + "extra": { + "magento_version": "2.4.6-p2" } } diff --git a/resource/history/mage-os/product-community-edition/1.0.1.json b/resource/history/mage-os/product-community-edition/1.0.1.json index e9f3781..37a9856 100644 --- a/resource/history/mage-os/product-community-edition/1.0.1.json +++ b/resource/history/mage-os/product-community-edition/1.0.1.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.0", "mage-os/inventory-metapackage": "1.0.0", "mage-os/page-builder": "1.0.0" + }, + "extra": { + "magento_version": "2.4.6-p3" } } diff --git a/resource/history/mage-os/product-community-edition/1.0.2.json b/resource/history/mage-os/product-community-edition/1.0.2.json index 2fcde68..032fa08 100644 --- a/resource/history/mage-os/product-community-edition/1.0.2.json +++ b/resource/history/mage-os/product-community-edition/1.0.2.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.2", "mage-os/inventory-metapackage": "1.0.2", "mage-os/page-builder": "1.0.2" + }, + "extra": { + "magento_version": "2.4.7-p1" } } diff --git a/resource/history/mage-os/product-community-edition/1.0.3.json b/resource/history/mage-os/product-community-edition/1.0.3.json index 6ae3e46..df5c16d 100644 --- a/resource/history/mage-os/product-community-edition/1.0.3.json +++ b/resource/history/mage-os/product-community-edition/1.0.3.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.3", "mage-os/inventory-metapackage": "1.0.3", "mage-os/page-builder": "1.0.3" + }, + "extra": { + "magento_version": "2.4.7-p1" } } diff --git a/resource/history/mage-os/product-community-edition/1.0.4.json b/resource/history/mage-os/product-community-edition/1.0.4.json index b7e2f12..05808e3 100644 --- a/resource/history/mage-os/product-community-edition/1.0.4.json +++ b/resource/history/mage-os/product-community-edition/1.0.4.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.4", "mage-os/inventory-metapackage": "1.0.4", "mage-os/page-builder": "1.0.4" + }, + "extra": { + "magento_version": "2.4.7-p2" } } diff --git a/resource/history/mage-os/product-community-edition/1.0.5.json b/resource/history/mage-os/product-community-edition/1.0.5.json index 6e87670..ec5ee25 100644 --- a/resource/history/mage-os/product-community-edition/1.0.5.json +++ b/resource/history/mage-os/product-community-edition/1.0.5.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.5", "mage-os/inventory-metapackage": "1.0.5", "mage-os/page-builder": "1.0.5" + }, + "extra": { + "magento_version": "2.4.7-p3" } } diff --git a/resource/history/mage-os/product-community-edition/1.0.6.json b/resource/history/mage-os/product-community-edition/1.0.6.json index 3b7a415..360bc6d 100644 --- a/resource/history/mage-os/product-community-edition/1.0.6.json +++ b/resource/history/mage-os/product-community-edition/1.0.6.json @@ -3,5 +3,8 @@ "mage-os/security-package": "1.0.6", "mage-os/inventory-metapackage": "1.0.6", "mage-os/page-builder": "1.0.6" + }, + "extra": { + "magento_version": "2.4.7-p4" } } diff --git a/resource/history/mage-os/product-community-edition/1.1.0.json b/resource/history/mage-os/product-community-edition/1.1.0.json index 5a8ec8b..c92587d 100644 --- a/resource/history/mage-os/product-community-edition/1.1.0.json +++ b/resource/history/mage-os/product-community-edition/1.1.0.json @@ -5,5 +5,8 @@ "mage-os/inventory-metapackage": "1.1.0", "mage-os/page-builder": "1.1.0", "mage-os/theme-adminhtml-m137": "1.1.0" + }, + "extra": { + "magento_version": "2.4.8" } } diff --git a/resource/history/mage-os/product-community-edition/1.1.1.json b/resource/history/mage-os/product-community-edition/1.1.1.json index f262814..adc7f7b 100644 --- a/resource/history/mage-os/product-community-edition/1.1.1.json +++ b/resource/history/mage-os/product-community-edition/1.1.1.json @@ -5,5 +5,8 @@ "mage-os/inventory-metapackage": "1.1.1", "mage-os/page-builder": "1.1.1", "mage-os/theme-adminhtml-m137": "1.1.1" + }, + "extra": { + "magento_version": "2.4.8" } } diff --git a/resource/history/mage-os/product-community-edition/1.2.0.json b/resource/history/mage-os/product-community-edition/1.2.0.json index 4bd9fc3..46fe99a 100644 --- a/resource/history/mage-os/product-community-edition/1.2.0.json +++ b/resource/history/mage-os/product-community-edition/1.2.0.json @@ -5,5 +5,8 @@ "mage-os/inventory-metapackage": "1.2.0", "mage-os/page-builder": "1.2.0", "mage-os/theme-adminhtml-m137": "1.2.0" + }, + "extra": { + "magento_version": "2.4.8-p1" } } diff --git a/resource/history/mage-os/product-community-edition/1.3.0.json b/resource/history/mage-os/product-community-edition/1.3.0.json index 4fec04a..da37369 100644 --- a/resource/history/mage-os/product-community-edition/1.3.0.json +++ b/resource/history/mage-os/product-community-edition/1.3.0.json @@ -5,5 +5,8 @@ "mage-os/inventory-metapackage": "1.3.0", "mage-os/page-builder": "1.3.0", "mage-os/theme-adminhtml-m137": "1.3.0" + }, + "extra": { + "magento_version": "2.4.8-p2" } } diff --git a/resource/history/mage-os/product-community-edition/1.3.1.json b/resource/history/mage-os/product-community-edition/1.3.1.json index 0b422df..e05add5 100644 --- a/resource/history/mage-os/product-community-edition/1.3.1.json +++ b/resource/history/mage-os/product-community-edition/1.3.1.json @@ -5,5 +5,8 @@ "mage-os/inventory-metapackage": "1.3.1", "mage-os/page-builder": "1.3.1", "mage-os/theme-adminhtml-m137": "1.3.1" + }, + "extra": { + "magento_version": "2.4.8-p2" } } diff --git a/src/build-config/mageos-release-build-config.js b/src/build-config/mageos-release-build-config.js index 02a90f3..a1138fa 100644 --- a/src/build-config/mageos-release-build-config.js +++ b/src/build-config/mageos-release-build-config.js @@ -1,3 +1,11 @@ +const { + transformMagentoCommunityEditionProject, + transformMagentoCommunityEditionProduct +} = require('../build-metapackage/magento-community-edition'); +const { + transformMageOSCommunityEditionProject, + transformMageOSCommunityEditionProduct +} = require('../build-metapackage/mage-os-community-edition'); const packagesConfig = require('./packages-config'); const {mergeBuildConfigs} = require('../utils'); @@ -13,6 +21,28 @@ const releaseBuildConfig = { composerJsonPath: `${__dirname}/../../resource/composer-templates/mage-os/magento2-base/template.json`, } ], + extraMetapackages: [ + { + name: 'project-community-edition', + type: 'project', + fromTag: '1.0.0', + description: 'Mage-OS Community Edition Project', + transform: [ + transformMagentoCommunityEditionProject, + transformMageOSCommunityEditionProject, + ] + }, + { + name: 'product-community-edition', + type: 'metapackage', + fromTag: '1.0.0', + description: 'Mage-OS Community Edition', + transform: [ + transformMagentoCommunityEditionProduct, + transformMageOSCommunityEditionProduct, + ] + } + ] }, 'security-package': { repoUrl: 'https://github.com/mage-os/mageos-security-package.git', @@ -124,214 +154,6 @@ const releaseBuildConfig = { ref: 'main', fromTag: '1.0.0', }, - // 'theme-adminhtml-m137': { - // repoUrl: 'https://github.com/mage-os-lab/theme-adminhtml-m137.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'theme-adminhtml-m137', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-theme-adminhtml-switcher': { - // repoUrl: 'https://github.com/mage-os-lab/module-theme-adminhtml-switcher.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-theme-adminhtml-switcher', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'mageos-async-events-sinks': { - // repoUrl: 'https://github.com/mage-os/mageos-async-events-sinks.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'mageos-async-events-sinks', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'mageos-async-events-admin-ui': { - // repoUrl: 'https://github.com/mage-os/mageos-async-events-admin-ui.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'mageos-async-events-admin-ui', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // // 'mageos-async-events-azure': { - // // repoUrl: 'https://github.com/mage-os/mageos-async-events-azure.git', - // // ref: 'main', - // // fromTag: '1.0.0', - // // packageDirs: [], - // // packageIndividual: [ - // // { - // // label: 'mageos-async-events-azure', - // // dir: '' - // // } - // // ], - // // packageMetaFromDirs: [], - // // }, - // 'mageos-async-events': { - // repoUrl: 'https://github.com/mage-os/mageos-async-events.git', - // ref: '4.x', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'mageos-async-events', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'mageos-async-events-aws': { - // repoUrl: 'https://github.com/mage-os/mageos-async-events-aws.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'mageos-async-events-aws', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'mageos-async-events-gcp': { - // repoUrl: 'https://github.com/mage-os/mageos-async-events-gcp.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'mageos-async-events-gcp', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'mageos-common-async-events': { - // repoUrl: 'https://github.com/mage-os/mageos-common-async-events.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'mageos-common-async-events', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-inventory-reservations-grid': { - // repoUrl: 'https://github.com/mage-os-lab/module-inventory-reservations-grid.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-inventory-reservations-grid', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-automatic-translation': { - // repoUrl: 'https://github.com/mage-os-lab/module-automatic-translation.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-automatic-translation', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'web-installer': { - // repoUrl: 'https://github.com/mage-os-lab/web-installer.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'web-installer', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-meta-robots-tag': { - // repoUrl: 'https://github.com/mage-os-lab/module-meta-robots-tag.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-meta-robots-tag', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-catalog-data-ai': { - // repoUrl: 'https://github.com/mage-os-lab/module-catalog-data-ai.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-catalog-data-ai', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-pagebuilder-template-import-export': { - // repoUrl: 'https://github.com/mage-os-lab/module-pagebuilder-template-import-export.git', - // ref: 'master', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-pagebuilder-template-import-export', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, - // 'module-admin-assistant': { - // repoUrl: 'https://github.com/mage-os-lab/module-admin-assistant.git', - // ref: 'main', - // fromTag: '1.0.0', - // packageDirs: [], - // packageIndividual: [ - // { - // label: 'module-admin-assistant', - // dir: '' - // } - // ], - // packageMetaFromDirs: [], - // }, }; module.exports = { diff --git a/src/build-config/packages-config.js b/src/build-config/packages-config.js index 88591bd..09c999c 100644 --- a/src/build-config/packages-config.js +++ b/src/build-config/packages-config.js @@ -1,10 +1,12 @@ +const { + transformMagentoCommunityEditionProject, + transformMagentoCommunityEditionProduct +} = require('../build-metapackage/magento-community-edition'); + const packageDefs = { 'magento2': { repoUrl: 'https://github.com/mage-os/mirror-magento2.git', - magentoCommunityEditionProject: true, - magentoCommunityEditionMetapackage: true, - packageDirs: [ {label: 'Magento Core Modules', dir: 'app/code/Magento'}, {label: 'Magento Language packages', dir: 'app/i18n/Magento'} @@ -69,6 +71,24 @@ const packageDefs = { }, ], packageMetaFromDirs: [], + extraMetapackages: [ + { + name: 'project-community-edition', + type: 'project', + description: 'Magento Community Edition Project', + transform: [ + transformMagentoCommunityEditionProject + ] + }, + { + name: 'product-community-edition', + type: 'metapackage', + description: 'Magento Community Edition', + transform: [ + transformMagentoCommunityEditionProduct + ] + } + ] }, 'security-package': { repoUrl: 'https://github.com/mage-os/mirror-security-package.git', diff --git a/src/build-metapackage/mage-os-community-edition.js b/src/build-metapackage/mage-os-community-edition.js new file mode 100644 index 0000000..7097f96 --- /dev/null +++ b/src/build-metapackage/mage-os-community-edition.js @@ -0,0 +1,47 @@ +const buildState = require('../type/build-state'); +const metapackageDefinition = require('../type/metapackage-definition'); +const repositoryBuildDefinition = require('../type/repository-build-definition'); +const {compareVersions} = require('../utils'); +const { + updateComposerConfigFromMagentoToMageOs +} = require('../release-build-tools'); + +/** + * @param {{}} composerConfig + * @param {repositoryBuildDefinition} instruction + * @param {metapackageDefinition} metapackage + * @param {buildState} release + */ +async function transformMageOSCommunityEditionProject(composerConfig, instruction, metapackage, release) { + updateComposerConfigFromMagentoToMageOs(instruction, release, composerConfig); + + // Versions 2.0.0 and below had a different description + if (compareVersions(composerConfig.version, '2.0.0') <= 0) { + composerConfig.description = 'eCommerce Platform for Growth (Community Edition)'; + } + + return composerConfig; +} + +/** + * @param {{}} composerConfig + * @param {repositoryBuildDefinition} instruction + * @param {metapackageDefinition} metapackage + * @param {buildState} release + */ +async function transformMageOSCommunityEditionProduct(composerConfig, instruction, metapackage, release) { + updateComposerConfigFromMagentoToMageOs(instruction, release, composerConfig) + + if (release.replaceVersions['magento/product-community-edition']) { + // Add upstreamRelease to composer extra data for reference + composerConfig.extra = composerConfig.extra || {}; + composerConfig.extra.magento_version = release.replaceVersions['magento/product-community-edition']; + } + + return composerConfig +} + +module.exports = { + transformMageOSCommunityEditionProject, + transformMageOSCommunityEditionProduct, +}; diff --git a/src/build-metapackage/magento-community-edition.js b/src/build-metapackage/magento-community-edition.js new file mode 100644 index 0000000..b1ca123 --- /dev/null +++ b/src/build-metapackage/magento-community-edition.js @@ -0,0 +1,100 @@ +const { + getVersionStability, + setDependencyVersions, + getAdditionalConfiguration +} = require('../package-modules'); +const buildState = require('../type/build-state'); +const metapackageDefinition = require('../type/metapackage-definition'); +const repositoryBuildDefinition = require('../type/repository-build-definition'); + +/** + * @param {{}} composerConfig + * @param {repositoryBuildDefinition} instruction + * @param {metapackageDefinition} metapackage + * @param {buildState} release + */ +async function transformMagentoCommunityEditionProject(composerConfig, instruction, metapackage, release) { + const packageName = `${instruction.vendor}/${metapackage.name}`; + const productName = `${instruction.vendor}/` + metapackage.name.replace('project-', 'product-'); + const version = release.version || release.dependencyVersions[packageName] || release.ref; + + // read release history or dependencies-template for project metapackage + const additionalConfig = await getAdditionalConfiguration(packageName, release.ref) + + // If this is not a new release, and additionalConfig looks like a full composer config, use it directly. + if (release.dependencyVersions['*'] === undefined && additionalConfig['prefer-stable'] !== undefined) { + return additionalConfig; + } + + composerConfig = Object.assign({}, composerConfig, additionalConfig, { + name: packageName, + description: 'Community-built eCommerce Platform for Growth', + extra: {'magento-force': 'override'}, + repositories: [{type: 'composer', url: release.composerRepoUrl}], + 'minimum-stability': getVersionStability(version), + require: Object.assign( + {[`${productName}`]: version}, + additionalConfig.require + ) + }); + + for (const k of ['replace', 'suggest']) { + delete composerConfig[k]; + } + + setDependencyVersions(instruction, release, composerConfig); + + return composerConfig; +} + +/** + * @param {{}} composerConfig + * @param {repositoryBuildDefinition} instruction + * @param {metapackageDefinition} metapackage + * @param {buildState} release + */ +async function transformMagentoCommunityEditionProduct(composerConfig, instruction, metapackage, release) { + const packageName = `${instruction.vendor}/${metapackage.name}`; + + // This method is in package-modules, and checks history and falls back to composer-templates + // We should find a way to consolidate or abstract this for other instances + const additionalConfig = await getAdditionalConfiguration(packageName, release.ref) + + // If this is not a new release, and additionalConfig looks like a full composer config, use it directly. + if (release.dependencyVersions['*'] === undefined && additionalConfig['prefer-stable'] !== undefined) { + return additionalConfig; + } + + delete composerConfig.extra; + + // For all entries in composerConfig.replace, pull all first-party replacements (magento/ modules) for requirements. + const replace = composerConfig?.replace ?? {}; + const vendorReplacements = Object.fromEntries( + Object.entries(replace).filter(([pkg]) => pkg.startsWith(`${instruction.vendor}/`) || pkg.startsWith('magento/')) + ); + + composerConfig = Object.assign({}, composerConfig, additionalConfig, { + name: packageName, + description: 'eCommerce Platform for Growth (Community Edition)', + type: 'metapackage', + require: Object.assign( + {}, + composerConfig.require, + vendorReplacements, + additionalConfig.require, + {[`${instruction.vendor}/magento2-base`]: release.version || composerConfig.version} + ), + }); + + for (const k of ['autoload', 'autoload-dev', 'config', 'conflict', 'minimum-stability', 'replace', 'require-dev', 'suggest']) { + delete composerConfig[k]; + } + setDependencyVersions(instruction, release, composerConfig); + + return composerConfig; +} + +module.exports = { + transformMagentoCommunityEditionProject, + transformMagentoCommunityEditionProduct, +}; diff --git a/src/make/mageos-nightly.js b/src/make/mageos-nightly.js index 4eb4e17..8b25000 100644 --- a/src/make/mageos-nightly.js +++ b/src/make/mageos-nightly.js @@ -1,6 +1,6 @@ const repo = require('./../repository'); const parseOptions = require('parse-options'); -const {setArchiveBaseDir, setMageosPackageRepoUrl} = require('./../package-modules'); +const {setArchiveBaseDir} = require('./../package-modules'); const {processNightlyBuildInstructions} = require('./../release-branch-build-tools'); const {buildConfig: branchBuildInstructions} = require('./../build-config/mageos-nightly-build-config'); @@ -31,9 +31,9 @@ if (options.gitRepoDir) { repo.setStorageDir(options.gitRepoDir); } -if (options.repoUrl) { - setMageosPackageRepoUrl(options.repoUrl); -} +let releaseContext = new buildState({ + composerRepoUrl: options.repoUrl || 'https://nightly.mage-os.org/', +}); -processNightlyBuildInstructions(branchBuildInstructions); +processNightlyBuildInstructions(branchBuildInstructions, releaseContext); diff --git a/src/make/mageos-release.js b/src/make/mageos-release.js index a3b8ce4..0de82f1 100644 --- a/src/make/mageos-release.js +++ b/src/make/mageos-release.js @@ -7,11 +7,9 @@ const { prepRelease, processBuildInstructions, validateVersionString, - updateComposerConfigFromMagentoToMageOs, } = require('./../release-build-tools'); const { setArchiveBaseDir, - setMageosPackageRepoUrl, } = require("../package-modules"); const {buildConfig: releaseInstructions} = require('./../build-config/mageos-release-build-config'); const {processMirrorInstruction} = require("../mirror-build-tools"); @@ -51,12 +49,9 @@ if (options.gitRepoDir) { repo.setStorageDir(options.gitRepoDir); } -if (options.repoUrl) { - setMageosPackageRepoUrl(options.repoUrl); -} - const mageosRelease = options.mageosRelease || ''; const mageosVendor = options.mageosVendor || 'mage-os'; +const mageosRepoUrl = options.repoUrl || 'https://repo.mage-os.org/'; const upstreamRelease = options.upstreamRelease || ''; const releaseRefsFile = options.releaseRefsFile || path.join(__dirname, `./../build-config/${mageosVendor}-release-refs/${mageosRelease}.js`); @@ -73,6 +68,7 @@ const releaseRefs = fs.existsSync(releaseRefsFile) let distroRelease = new buildState({ version: mageosRelease, + composerRepoUrl: mageosRepoUrl, fallbackVersion: mageosRelease, dependencyVersions: {'*': mageosRelease} }); @@ -84,21 +80,9 @@ let distroRelease = new buildState({ if (! skipHistory) { console.log(`Building previous ${mageosVendor} releases`) for (const instruction of releaseInstructions) { - // set vendor for product-community-edition and project-community-edition meta packages - if (instruction.magentoCommunityEditionProject || instruction.magentoCommunityEditionMetapackage) { - instruction.vendor = mageosVendor - } - if (instruction.magentoCommunityEditionMetapackage) { - // update product package magento dependencies taken from the root composer.json to given vendor - const productPackage = `${mageosVendor}/product-community-edition`; - - instruction.transform[productPackage] = instruction.transform[productPackage] || []; - instruction.transform[productPackage].push((composerConfig, instruction, release) => { - updateComposerConfigFromMagentoToMageOs(instruction, release, composerConfig) - return composerConfig - }) - } - await processMirrorInstruction(instruction) + instruction.vendor = mageosVendor; + + await processMirrorInstruction(instruction, distroRelease); } } diff --git a/src/make/mirror.js b/src/make/mirror.js index 4a00376..d47d238 100644 --- a/src/make/mirror.js +++ b/src/make/mirror.js @@ -1,8 +1,9 @@ const repo = require('./../repository'); const parseOptions = require('parse-options'); -const {setArchiveBaseDir, setMageosPackageRepoUrl} = require('./../package-modules'); +const {setArchiveBaseDir} = require('./../package-modules'); const {copyAdditionalPackages, processMirrorInstruction} = require('./../mirror-build-tools'); const {buildConfig: mirrorInstructions} = require('./../build-config/mirror-build-config'); +const buildState = require('../type/build-state'); const options = parseOptions( @@ -32,15 +33,15 @@ if (options.gitRepoDir) { repo.setStorageDir(options.gitRepoDir); } -if (options.repoUrl) { - setMageosPackageRepoUrl(options.repoUrl); -} +let releaseContext = new buildState({ + composerRepoUrl: options.repoUrl || 'https://mirror.mage-os.org/', +}); (async () => { try { for (const instruction of mirrorInstructions) { - await processMirrorInstruction(instruction); + await processMirrorInstruction(instruction, releaseContext); } await copyAdditionalPackages(archiveDir); } catch (exception) { diff --git a/src/mirror-build-tools.js b/src/mirror-build-tools.js index b19d972..8751c53 100644 --- a/src/mirror-build-tools.js +++ b/src/mirror-build-tools.js @@ -5,10 +5,9 @@ const zip = require('jszip'); const { createPackagesForRef, createPackageForRef, - createMagentoCommunityEditionMetapackage, - createMagentoCommunityEditionProject, createMetaPackageFromRepoDir, - archiveFilePath + archiveFilePath, + createComposerJsonOnlyPackage } = require('./package-modules'); const repositoryBuildDefinition = require('./type/repository-build-definition'); const packageDefinition = require('./type/package-definition'); @@ -55,54 +54,6 @@ async function copyAdditionalPackages(archiveDir) { } } -/** - * @param {repositoryBuildDefinition} instruction - * @returns {Array} Packaged tags - */ -async function createMagentoCommunityEditionMetapackagesSinceTag(instruction) { - const tags = await listTagsFrom(instruction.repoUrl, instruction.fromTag, instruction.skipTags); - console.log(`Versions to process: ${tags.join(', ')}`); - for (const tag of tags) { - console.log(`Processing ${tag}`); - - let release = new buildState({ - ref: tag, - fallbackVersion: tag, - dependencyVersions: (instruction.fixVersions?.[tag] ?? {}) - }); - - await createMagentoCommunityEditionMetapackage( - instruction, - release - ); - } - return tags; -} - -/** - * @param {repositoryBuildDefinition} instruction - * @returns {Array} Packaged tags - */ -async function createProjectPackagesSinceTag(instruction) { - const tags = await listTagsFrom(instruction.repoUrl, instruction.fromTag, instruction.skipTags); - console.log(`Versions to process: ${tags.join(', ')}`); - for (const tag of tags) { - console.log(`Processing ${tag}`); - - let release = new buildState({ - ref: tag, - fallbackVersion: tag, - dependencyVersions: (instruction.fixVersions?.[tag] ?? {}) - }); - - await createMagentoCommunityEditionProject( - instruction, - release - ); - } - return tags; -} - /** * @param {repositoryBuildDefinition} instruction * @param {packageDefinition} package @@ -244,9 +195,52 @@ async function replacePackageFiles(package) { /** * @param {repositoryBuildDefinition} instruction + * @param {Object} metapackage + * @param {buildState} releaseContext + * @returns {Array} Packaged tags + */ +async function createMetaPackagesSinceTag(instruction, metapackage, releaseContext) { + const packageName = `${instruction.vendor}/${metapackage.name}`; + const tags = await listTagsFrom( + instruction.repoUrl, + metapackage.fromTag || instruction.fromTag, + instruction.skipTags + ); + console.log(`Versions to process for metapackage ${packageName}: ${tags.join(', ')}`); + + for (const tag of tags) { + console.log(`Processing ${tag}`); + let release = new buildState({ + ref: tag, + composerRepoUrl: releaseContext.composerRepoUrl, + fallbackVersion: tag, + dependencyVersions: (instruction.fixVersions?.[tag] ?? {}) + }); + + await createComposerJsonOnlyPackage( + instruction, + release, + packageName, + tag, + async composerConfig => { + if (metapackage.transform) { + for (const fn of metapackage.transform) { + composerConfig = await fn(composerConfig, instruction, metapackage, release); + } + } + return composerConfig; + } + ); + } + return tags; +} + +/** + * @param {repositoryBuildDefinition} instruction + * @param {buildState} releaseContext * @returns {Promise} */ -async function processMirrorInstruction(instruction) { +async function processMirrorInstruction(instruction, releaseContext) { let tags = []; await Promise.all( @@ -277,16 +271,9 @@ async function processMirrorInstruction(instruction) { await replacePackageFiles(packageReplacement); } - if (instruction.magentoCommunityEditionMetapackage) { - console.log('Packaging Magento Community Edition Product Metapackage'); - tags = await createMagentoCommunityEditionMetapackagesSinceTag(instruction); - console.log('Magento Community Edition Product Metapackage', tags); - } - - if (instruction.magentoCommunityEditionProject) { - console.log('Packaging Magento Community Edition Project'); - tags = await createProjectPackagesSinceTag(instruction); - console.log('Magento Community Edition Project', tags); + for (const metapackage of instruction.extraMetapackages) { + console.log(`Packaging ${metapackage.name}`); + tags = await createMetaPackagesSinceTag(instruction, metapackage, releaseContext); } repo.clearCache(); diff --git a/src/package-modules.js b/src/package-modules.js index bdb68b8..5351308 100644 --- a/src/package-modules.js +++ b/src/package-modules.js @@ -11,8 +11,6 @@ const buildState = require('./type/build-state'); let archiveBaseDir = 'packages'; -let mageosPackageRepoUrl = 'https://repo.mage-os.org/'; - const stableMtime = '2022-02-22 22:02:22.000Z'; function report() { @@ -85,9 +83,9 @@ async function writePackage(packageFilepath, files) { } /** - * @param {repositoryBuildDefinition} instruction - * @param {packageDefinition} package - * @param {String} ref + * @param {repositoryBuildDefinition} instruction + * @param {packageDefinition} package + * @param {String} ref * @returns {String} */ async function getComposerJson(instruction, package, ref) { @@ -107,7 +105,7 @@ async function getComposerJson(instruction, package, ref) { */ function getVersionStability(version) { version = version.toLowerCase(); - + if (version.startsWith('dev-') || version.includes('-dev')) { return 'dev'; } @@ -125,13 +123,13 @@ function getVersionStability(version) { } /** - * @param {repositoryBuildDefinition} instruction - * @param {packageDefinition} package - * @param {*} magentoName - * @param {*} composerJson - * @param {*} definedVersion - * @param {*} fallbackVersion - * @returns + * @param {repositoryBuildDefinition} instruction + * @param {packageDefinition} package + * @param {*} magentoName + * @param {*} composerJson + * @param {*} definedVersion + * @param {*} fallbackVersion + * @returns */ function chooseNameAndVersion(instruction, package, magentoName, composerJson, definedVersion, fallbackVersion) { let composerConfig = JSON.parse(composerJson); @@ -194,8 +192,8 @@ function setDependencyVersions(instruction, release, composerConfig) { * * Only used for release-branch builds (not mirror builds). * - * @param {repositoryBuildDefinition} instruction - * @param {packageDefinition} package + * @param {repositoryBuildDefinition} instruction + * @param {packageDefinition} package * @returns {Promise>} */ async function determinePackageForRef(instruction, package, ref) { @@ -227,8 +225,8 @@ async function determinePackageForRef(instruction, package, ref) { * * Only used for release-branch builds (not mirror builds). * - * @param {repositoryBuildDefinition} instruction - * @param {packageDefinition} package + * @param {repositoryBuildDefinition} instruction + * @param {packageDefinition} package * @returns {Promise>} */ async function determinePackagesForRef(instruction, package, ref) { @@ -243,7 +241,7 @@ async function determinePackagesForRef(instruction, package, ref) { } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {packageDefinition} package * @param {buildState} release * @returns {Promise<{}>} @@ -337,10 +335,9 @@ async function createPackageForRef(instruction, package, release) { setDependencyVersions(instruction, release, composerConfig); if (instruction.transform[name]) { - composerConfig = instruction.transform[name].reduce( - (config, transformFn) => transformFn(config, instruction, release), - composerConfig - ); + for (const fn of instruction.transform[name]) { + composerConfig = await fn(composerConfig, instruction, release); + } } const filesInZip = files.map(file => { @@ -384,7 +381,7 @@ function isInAdditionalPackages(name, version) { } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @param {String} name The composer name to use in the composer.json and for the package archive * @param {String|undefined} version Release version to use in the package archive name. Defaults to ref @@ -402,8 +399,25 @@ async function createComposerJsonOnlyPackage(instruction, release, name, version isExecutable: false, }]; + // Special case - in these releases the base package also contained a .gitignore file in addition to the composer.json file. + // The .gitignore file is identical for those two releases. However, it is not the same as the .gitignore file in the tagged release, + // so we copy it from resource/history/magento/project-community-edition/2.4.0-gitignore + if (name === 'magento/project-community-edition' && (release.ref === '2.4.0' || release.ref === '2.4.0-p1')) { + files.push({ + filepath: '.gitignore', + mtime: new Date(stableMtime), + contentBuffer: fs.readFileSync(`${__dirname}/../resource/history/magento/project-community-edition/2.4.0-gitignore`), + isExecutable: false, + }) + } + // @todo: Check version vs instruction.ref vs release.version here. Is this necessary to track separately? Is this fallback needed? const packageFilepath = archiveFilePath(name, version || release.ref); + + if (!isInAdditionalPackages(name, composerConfig.version)) { + await writePackage(packageFilepath, files); + } + return {packageFilepath, files} } @@ -413,28 +427,31 @@ async function getLatestTag(url) { return tags[tags.length - 1]; } -async function getLatestDependencies(dir) { +async function getLatestConfiguration(dir) { if (!fs.existsSync(`${dir}/dependencies-template.json`)) { - return {}; + return { + require: {} + }; } const template = JSON.parse(fs.readFileSync(`${dir}/dependencies-template.json`, 'utf8')); return Object.entries(template.dependencies).reduce(async (deps, [dependency, url]) => { - const tag = url.slice(0, 4) === 'http' ? await getLatestTag(url) : url; - return Object.assign(await deps, {[dependency]: tag}); - }, Promise.resolve({})); + const tag = url.slice(0, 4) === 'http' ? await getLatestTag(url) : url; + return Object.assign(await deps, {[dependency]: tag}); + }, Promise.resolve({})) + .then(requireObj => ({ require: requireObj })); } -async function getAdditionalDependencies(packageName, ref) { +async function getAdditionalConfiguration(packageName, ref) { const dir = `${__dirname}/../resource/history/${packageName}`; const file = `${dir}/${ref}.json`; return fs.existsSync(file) - ? JSON.parse(fs.readFileSync(file, 'utf8')).require - : await getLatestDependencies(`${__dirname}/../resource/composer-templates/${packageName}`); + ? JSON.parse(fs.readFileSync(file, 'utf8')) + : await getLatestConfiguration(`${__dirname}/../resource/composer-templates/${packageName}`); } /** - * @param {repositoryBuildDefinition} instruction - * @param {packageDefinition} package + * @param {repositoryBuildDefinition} instruction + * @param {packageDefinition} package * @returns Array */ async function findModulesToBuild(instruction, package, ref) { @@ -450,8 +467,8 @@ async function findModulesToBuild(instruction, package, ref) { } /** - * @param {repositoryBuildDefinition} instruction - * @param {packageDefinition} package + * @param {repositoryBuildDefinition} instruction + * @param {packageDefinition} package * @param {buildState} release * @returns {Promise<{}>} */ @@ -485,169 +502,6 @@ async function createPackagesForRef(instruction, package, release) { return built; } -async function determineMagentoCommunityEditionMetapackage(repoUrl, ref, release) { - const version = release || ref; - return {'magento/product-community-edition': version}; -} - -/** - * @param {repositoryBuildDefinition} instruction - * @param {buildState} release - * @param {{transform:{}}} options - * @returns {Promise<{}>} - */ -async function createMagentoCommunityEditionMetapackage(instruction, release, options) { - const defaults = { - transform: {}, - }; - const {transform} = Object.assign(defaults, (options || {})) - - const packageName = `${instruction.vendor}/product-community-edition` - const version = release.version || release.dependencyVersions[packageName] || release.ref; - const { - packageFilepath, - files - } = await createComposerJsonOnlyPackage( - instruction, - release, - packageName, - version, - async (refComposerConfig) => { - // read release history or dependencies-template for product metapackage - const additionalDependencies = await getAdditionalDependencies(packageName, release.ref) - - let composerConfig = Object.assign({}, refComposerConfig, { - name: packageName, - description: 'eCommerce Platform for Growth (Community Edition)', - type: 'metapackage', - require: Object.assign( - {}, - refComposerConfig.require, - refComposerConfig.replace, - additionalDependencies, - {[`${instruction.vendor}/magento2-base`]: version} - ), - version - }); - - for (const k of ['autoload', 'autoload-dev', 'config', 'conflict', 'extra', 'minimum-stability', 'replace', 'require-dev', 'suggest']) { - delete composerConfig[k]; - } - setDependencyVersions(instruction, release, composerConfig); - - if (instruction.transform[packageName]) { - composerConfig = instruction.transform[packageName].reduce( - (config, transformFn) => transformFn(config, instruction, release), - composerConfig - ); - } - if (transform[packageName]) { - composerConfig = transform[packageName].reduce( - (config, transformFn) => transformFn(config, instruction, release), - composerConfig - ); - } - - return composerConfig; - } - ); - - if (! isInAdditionalPackages(packageName, version)) { - await writePackage(packageFilepath, files); - } - - return {[packageName]: version}; -} - -async function determineMagentoCommunityEditionProject(url, ref, release) { - const version = release || ref; - return {'magento/project-community-edition': version} -} - -/** - * Options: - * release: Release version to use in composer.json version tag and in the package archive name. Defaults to ref - * dependencyVersions: composer package:version dependency map. Dependencies for packages in the map will be set to the given versions - * - * @param {repositoryBuildDefinition} instruction - * @param {buildState} release - * @param {{description:String|undefined, transform: Array}} options - * @returns {Promise<{}>} - */ -async function createMagentoCommunityEditionProject(instruction, release, options) { - const defaults = { - description: 'eCommerce Platform for Growth (Community Edition)', - transform: {}, - }; - const {description, transform} = Object.assign(defaults, (options || {})) - const name = `${instruction.vendor}/project-community-edition`; - const version = release.version || release.dependencyVersions[name] || release.ref; - const minimumStability = getVersionStability(version); - const {packageFilepath, files} = await createComposerJsonOnlyPackage( - instruction, - release, - name, - version, - async (refComposerConfig) => { - // read release history or dependencies-template for project metapackage - const additionalDependencies = await getAdditionalDependencies(name, release.ref) - - // Build project metapackage composer.json - let composerConfig = Object.assign(refComposerConfig, { - name: name, - description: description, - extra: {'magento-force': 'override'}, - version: version, - repositories: [{type: 'composer', url: mageosPackageRepoUrl}], - 'minimum-stability': minimumStability, - require: Object.assign( - {[`${instruction.vendor}/product-community-edition`]: version}, - additionalDependencies - ) - }); - - for (const k of ['replace', 'suggest']) { - delete composerConfig[k]; - } - - setDependencyVersions(instruction, release, composerConfig); - - if (instruction?.transform[name]) { - composerConfig = instruction.transform[name].reduce( - (config, transformFn) => transformFn(config, instruction, release), - composerConfig - ) - } - if (transform[name]) { - composerConfig = transform[name].reduce( - (config, transformFn) => transformFn(config, instruction, release), - composerConfig - ) - } - - return composerConfig; - } - ); - - // Special case - in these releases the base package also contained a .gitignore file in addition to the composer.json file. - // The .gitignore file is identical for those two releases. However, it is not the same as the .gitignore file in the tagged release, - // so we copy it from resource/history/magento/project-community-edition/2.4.0-gitignore - if (name === 'magento/project-community-edition' && (release.ref === '2.4.0' || release.ref === '2.4.0-p1')) { - files.push({ - filepath: '.gitignore', - mtime: new Date(stableMtime), - contentBuffer: fs.readFileSync(`${__dirname}/../resource/history/magento/project-community-edition/2.4.0-gitignore`), - isExecutable: false, - }) - } - - if (! isInAdditionalPackages(name, version)) { - await writePackage(packageFilepath, files); - } - - return {[name]: version} -} - /** * @param {String} url The URL of the source git repository * @param {String} dir The directory path to the git repository @@ -690,10 +544,9 @@ async function createMetaPackageFromRepoDir(instruction, package, release) { setDependencyVersions(instruction, release, composerConfig); if (instruction.transform[name]) { - composerConfig = instruction.transform[name].reduce( - (config, transformFn) => transformFn(config, instruction, release), - composerConfig - ); + for (const fn of instruction.transform[name]) { + composerConfig = await fn(composerConfig, instruction, release); + } } const files = [{ @@ -711,18 +564,63 @@ async function createMetaPackageFromRepoDir(instruction, package, release) { return {[name]: version} } +async function createMetaPackage(instruction, metapackage, release) { + let packageName = `magento/${metapackage.name}`; // Has to be Magento here for transforms. + + // Fetch base composer config + const composerJson = await readComposerJson(instruction.repoUrl, '', release.ref); + let composerConfig = JSON.parse(composerJson); + + // Create specific package config + composerConfig = Object.assign(composerConfig, { + name: packageName, + description: composerConfig.description || '', + type: metapackage.type, + license: composerConfig.license || [], + require: composerConfig.require || {}, + version: release.version || release.ref + }); + + // Apply transforms + if (instruction.transform[packageName]) { + for (const fn of instruction.transform[packageName]) { + composerConfig = await fn(composerConfig, instruction, release); + } + } + + for (const fn of metapackage.transform) { + composerConfig = await fn(composerConfig, instruction, metapackage, release); + } + + // Create package + const files = [{ + filepath: 'composer.json', + mtime: new Date(stableMtime), + contentBuffer: Buffer.from(JSON.stringify(composerConfig, null, 2), 'utf8'), + isExecutable: false + }]; + + // Update packageName with final vendor + packageName = `${instruction.vendor}/${metapackage.name}`; + + const packageFilepath = archiveFilePath(packageName, composerConfig.version); + + if (!isInAdditionalPackages(packageName, composerConfig.version)) { + await writePackage(packageFilepath, files); + } + + return {[packageName]: composerConfig.version}; +} + module.exports = { setArchiveBaseDir(newArchiveBaseDir) { archiveBaseDir = newArchiveBaseDir; }, - setMageosPackageRepoUrl(newMirrorUrl) { - mageosPackageRepoUrl = newMirrorUrl; - }, createPackageForRef, createPackagesForRef, - createMagentoCommunityEditionMetapackage, - createMagentoCommunityEditionProject, createMetaPackageFromRepoDir, + createMetaPackage, + createComposerJsonOnlyPackage, getLatestTag, archiveFilePath, @@ -730,7 +628,10 @@ module.exports = { determinePackageForRef, determinePackagesForRef, - determineMagentoCommunityEditionMetapackage, - determineMagentoCommunityEditionProject, determineMetaPackageFromRepoDir, + + getVersionStability, + setDependencyVersions, + getAdditionalDependencies: getAdditionalConfiguration, + getAdditionalConfiguration } diff --git a/src/release-branch-build-tools.js b/src/release-branch-build-tools.js index 1c0db79..ace3784 100644 --- a/src/release-branch-build-tools.js +++ b/src/release-branch-build-tools.js @@ -2,14 +2,11 @@ const repo = require("./repository"); const { createPackagesForRef, createPackageForRef, - createMagentoCommunityEditionMetapackage, - createMagentoCommunityEditionProject, + createMetaPackage, createMetaPackageFromRepoDir, determinePackagesForRef, determinePackageForRef, determineMetaPackageFromRepoDir, - determineMagentoCommunityEditionMetapackage, - determineMagentoCommunityEditionProject, getLatestTag } = require('./package-modules'); const repositoryBuildDefinition = require("./type/repository-build-definition"); @@ -46,16 +43,9 @@ async function getPackagesForBuildInstruction(instruction) { Object.assign(packages, toBeBuilt); } - if (instruction.magentoCommunityEditionMetapackage) { - console.log('Inspecting Magento Community Edition Product Metapackage'); - toBeBuilt = await determineMagentoCommunityEditionMetapackage(instruction.repoUrl, baseVersionsOnRef); - Object.assign(packages, toBeBuilt); - } - - if (instruction.magentoCommunityEditionProject) { - console.log('Inspecting Magento Community Edition Project'); - toBeBuilt = await determineMagentoCommunityEditionProject(instruction.repoUrl, baseVersionsOnRef); - Object.assign(packages, toBeBuilt); + for (const metapackage of (instruction.extraMetapackages || [])) { + console.log(`Inspecting ${metapackage.name}`); + packages[`${instruction.vendor}/${metapackage.name}`] = baseVersionsOnRef; } repo.clearCache(); @@ -146,18 +136,9 @@ async function processBuildInstruction(instruction, release) { Object.assign(packages, built); } - if (instruction.magentoCommunityEditionMetapackage) { - console.log('Packaging Magento Community Edition Product Metapackage'); - built = await createMagentoCommunityEditionMetapackage(instruction, release); - Object.assign(packages, built); - } - - if (instruction.magentoCommunityEditionProject) { - console.log('Packaging Magento Community Edition Project'); - built = await createMagentoCommunityEditionProject( - instruction, - release - ); + for (const metapackage of (instruction.extraMetapackages || [])) { + console.log(`Building metapackage ${metapackage.name}`); + const built = await createMetaPackage(instruction, metapackage, release); Object.assign(packages, built); } diff --git a/src/release-build-tools.js b/src/release-build-tools.js index c59ae00..c7bc022 100644 --- a/src/release-build-tools.js +++ b/src/release-build-tools.js @@ -4,11 +4,12 @@ const repo = require("./repository"); const {accessSync, constants} = require("fs"); const fs = require("fs/promises"); const path = require("path"); -const {readComposerJson, createMagentoCommunityEditionMetapackage, +const { + readComposerJson, createPackagesForRef, createPackageForRef, - createMetaPackageFromRepoDir, - createMagentoCommunityEditionProject + createMetaPackage, + createMetaPackageFromRepoDir } = require('./package-modules'); const {isOnPackagist} = require('./packagist'); const repositoryBuildDefinition = require('./type/repository-build-definition'); @@ -129,7 +130,7 @@ function updateMapFromMagentoToMageOs(obj, vendor) { } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @param {{}} composerConfig */ @@ -141,7 +142,7 @@ function updateComposerDepsFromMagentoToMageOs(instruction, release, composerCon } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @param {{}} composerConfigPart * @param {String} dependencyType @@ -156,7 +157,7 @@ function setMageOsDependencyVersion(instruction, release, composerConfigPart, de // Note: Original code here was just "release.version". The remainder are probably mostly unnecessary. Point for later refinement. composerConfigPart[packageName] = release.version || release.fallbackVersion || release.dependencyVersions[packageName] || release.dependencyVersions['*']; } - + if (dependencyType === 'suggest' && packageName.endsWith('-sample-data')) { composerConfigPart[packageName] = `Sample Data version: ${release.version || release.fallbackVersion}`; } @@ -166,7 +167,7 @@ function setMageOsDependencyVersion(instruction, release, composerConfigPart, de } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @param {{}} composerConfig */ @@ -177,7 +178,7 @@ function updateComposerDepsVersionForMageOs(instruction, release, composerConfig } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @param {{}} composerConfig */ @@ -196,7 +197,7 @@ function updateComposerPluginConfigForMageOs(instruction, release, composerConfi * * This also happens for the "replace" section, before the given replaceVersionMap is merged. * - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @param {{}} composerConfig */ @@ -205,7 +206,7 @@ function updateComposerConfigFromMagentoToMageOs(instruction, release, composerC composerConfig.version = release.version || release.ref; composerConfig.name = setMageOsVendor(composerConfig.name, instruction.vendor); - + updateComposerDepsFromMagentoToMageOs(instruction, release, composerConfig); updateComposerDepsVersionForMageOs(instruction, release, composerConfig); updateComposerPluginConfigForMageOs(instruction, release, composerConfig); @@ -216,10 +217,10 @@ function updateComposerConfigFromMagentoToMageOs(instruction, release, composerC } /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {packageDefinition} package * @param {buildState} release - * @param {String} workingCopyPath + * @param {String} workingCopyPath */ async function prepPackageForRelease(instruction, package, release, workingCopyPath) { console.log(`Preparing ${package.label}`); @@ -235,61 +236,6 @@ async function prepPackageForRelease(instruction, package, release, workingCopyP await fs.writeFile(file, JSON.stringify(composerConfig, null, 2), 'utf8'); } -/** - * @param {repositoryBuildDefinition} instruction - * @param {buildState} release - * @returns {Promise<{}>} - */ -async function buildMageOsProductCommunityEditionMetapackage(instruction, release) { - console.log('Packaging Mage-OS Community Edition Product Metapackage'); - - return createMagentoCommunityEditionMetapackage( - instruction, - release, - { - transform: { - [`${instruction.vendor}/product-community-edition`]: [ - (composerConfig) => { - updateComposerConfigFromMagentoToMageOs(instruction, release, composerConfig) - - // Add upstreamRelease to composer extra data for reference - composerConfig.extra = composerConfig.extra || {}; - composerConfig.extra.magento_version = release.replaceVersions['magento/product-community-edition']; - - return composerConfig - } - ] - } - } - ) -} - -/** - * @param {repositoryBuildDefinition} instruction - * @param {buildState} release - * @returns {Promise} - */ -async function buildMageOsProjectCommunityEditionMetapackage(instruction, release) { - console.log('Packaging Mage-OS Community Edition Project'); - - return createMagentoCommunityEditionProject( - instruction, - release, - { - description: 'Community-built eCommerce Platform for Growth', - transform: { - [`${instruction.vendor}/project-community-edition`]: [ - (composerConfig) => { - updateComposerConfigFromMagentoToMageOs(instruction, release, composerConfig) - return composerConfig - } - ] - } - } - ) -} - - module.exports = { validateVersionString, updateComposerConfigFromMagentoToMageOs, @@ -299,7 +245,7 @@ module.exports = { return getInstalledPackageMap(dir); }, /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @returns {void} */ @@ -351,24 +297,20 @@ module.exports = { await prepPackageForRelease(instruction, package, release, workingCopyPath); } - if (instruction.magentoCommunityEditionMetapackage) { - // nothing to do - the product-community-edition metapackage composer.json is built from a template - } - - if (instruction.magentoCommunityEditionProject) { - // update the base composer.json for releasing (doesn't happen for the base package because that uses a composer.json template) - const metapackage = new packageDefinition({ - 'label': 'Mage-OS Community Edition Project Metapackage', - 'dir': '' + const communityEdition = (instruction.extraMetapackages || []).find(package => package.name === 'project-community-edition'); + if (communityEdition) { + const package = new packageDefinition({ + label: communityEdition.description || communityEdition.name, + dir: '', // communityEdition metapackages use the root ./composer.json. Others generally use ./_metapackage/. }); - await prepPackageForRelease(instruction, metapackage, release, workingCopyPath); + await prepPackageForRelease(instruction, package, release, workingCopyPath); } return workBranch }, /** - * @param {repositoryBuildDefinition} instruction + * @param {repositoryBuildDefinition} instruction * @param {buildState} release * @returns {Object.} A map of built packages:versions */ @@ -406,14 +348,14 @@ module.exports = { Object.assign(packages, built) } - if (instruction.magentoCommunityEditionMetapackage) { - const built = await buildMageOsProductCommunityEditionMetapackage(instruction, release) - Object.assign(packages, built) - } - - if (instruction.magentoCommunityEditionProject) { - const built = await buildMageOsProjectCommunityEditionMetapackage(instruction, release) - Object.assign(packages, built) + for (const metapackage of (instruction.extraMetapackages || [])) { + console.log(`Building metapackage ${metapackage.name}`); + const built = await createMetaPackage( + instruction, + metapackage, + release + ); + Object.assign(packages, built); } return packages diff --git a/src/type/build-state.js b/src/type/build-state.js index a4de52c..4a60b13 100644 --- a/src/type/build-state.js +++ b/src/type/build-state.js @@ -20,6 +20,11 @@ class buildState { */ version = null; + /** + * @type String|null Git Repository URL + */ + composerRepoUrl = null; + /** * @type {String|null} Fallback version to use in composer.json version tag and * in the package archive name (used for nightly releases) @@ -39,13 +44,14 @@ class buildState { replaceVersions = {}; /** - * @param {{ref: String, origRef: String, version: String, fallbackVersion: String, dependencyVersions: Object., replaceVersions: Object.}}} options + * @param {{ref: String, origRef: String, version: String, composerRepoUrl: String, fallbackVersion: String, dependencyVersions: Object., replaceVersions: Object.}}} options */ constructor(options) { this.ref = options.ref || this.ref; this.origRef = options.origRef || this.origRef; this.version = options.version || this.version; this.fallbackVersion = options.fallbackVersion || this.fallbackVersion; + this.composerRepoUrl = options.composerRepoUrl || this.composerRepoUrl; this.dependencyVersions = options.dependencyVersions || this.dependencyVersions; this.replaceVersions = options.replaceVersions || this.replaceVersions; } diff --git a/src/type/metapackage-definition.js b/src/type/metapackage-definition.js new file mode 100644 index 0000000..17ee393 --- /dev/null +++ b/src/type/metapackage-definition.js @@ -0,0 +1,39 @@ +class metapackageDefinition { + /** + * @type String Package name + */ + name = ''; + + /** + * @type String Package type + */ + type = 'metapackage'; + + /** + * @type String Package description + */ + description = ''; + + /** + * @type Array Transform functions to apply + */ + transform = []; + + /** + * @type String|null Tag to build from (e.g. a git tag) + */ + fromTag = null; + + /** + * @param {{name: String, type: String, description: String, transform: Array, fromTag: String}} config + */ + constructor(config = {}) { + this.name = config.name || this.name; + this.type = config.type || this.type; + this.description = config.description || this.description; + this.transform = config.transform || this.transform; + this.fromTag = config.fromTag || this.fromTag; + } +} + +module.exports = metapackageDefinition; diff --git a/src/type/repository-build-definition.js b/src/type/repository-build-definition.js index f394730..e32c900 100644 --- a/src/type/repository-build-definition.js +++ b/src/type/repository-build-definition.js @@ -3,6 +3,7 @@ const extraRefToRelease = require('./extra-ref-to-release'); const packageDefinition = require('./package-definition'); const packageReplacement = require('./package-replacement'); +const metapackageDefinition = require('./metapackage-definition'); /** * Defines release build instructions for a git repository. @@ -31,14 +32,9 @@ class repositoryBuildDefinition { packageMetaFromDirs = []; /** - * @type Boolean Whether this package is a Magento project metapackage + * @type Array Create additional metapackages as defined */ - magentoCommunityEditionProject = false; - - /** - * @type Boolean Whether this package is a Magento product metapackage - */ - magentoCommunityEditionMetapackage = false; + extraMetapackages = []; /** * @type String Package vendor to use @@ -83,13 +79,10 @@ class repositoryBuildDefinition { extraRefToRelease = []; /** - * @param {{repoUrl: String, packageDirs: Array, packageIndividual: Array, packageMetaFromDirs: Array, magentoCommunityEditionProject: boolean, magentoCommunityEditionMetapackage: boolean, vendor: String, ref: String, fromTag: String, skipTags: {Object}, transform: Object., fixVersions: {Object}, packageReplacements: {Object}, extraRefToRelease: Array}} + * @param {{repoUrl: String, packageDirs: Array, packageIndividual: Array, packageMetaFromDirs: Array, vendor: String, ref: String, fromTag: String, skipTags: {Object}, transform: Object., fixVersions: {Object}, packageReplacements: {Object}, extraRefToRelease: Array, extraMetapackages: Array}} */ constructor(options) { this.repoUrl = options.repoUrl || this.repoUrl; - - this.magentoCommunityEditionProject = options.magentoCommunityEditionProject || this.magentoCommunityEditionProject; - this.magentoCommunityEditionMetapackage = options.magentoCommunityEditionMetapackage || this.magentoCommunityEditionMetapackage; this.vendor = options.vendor || this.vendor; this.ref = options.ref || this.ref; @@ -101,9 +94,10 @@ class repositoryBuildDefinition { this.packageDirs = this.initPackageDefinitions(options.packageDirs || []); this.packageIndividual = this.initPackageDefinitions(options.packageIndividual || []); this.packageMetaFromDirs = this.initPackageDefinitions(options.packageMetaFromDirs || []); - + this.packageReplacements = this.initPackageReplacements(options.packageReplacements || []); this.extraRefToRelease = this.initExtraRefsToRelease(options.extraRefToRelease || []); + this.extraMetapackages = this.initMetapackageDefinitions(options.extraMetapackages || []); } /** @@ -144,6 +138,19 @@ class repositoryBuildDefinition { return instances; } + + /** + * @param {Array<{}>} metapackages + * @returns {Array} + */ + initMetapackageDefinitions(metapackages) { + let instances = []; + metapackages.forEach(element => { + instances.push(new metapackageDefinition(element)); + }); + + return instances; + } }; module.exports = repositoryBuildDefinition; diff --git a/src/utils.js b/src/utils.js index 4ecdafb..c9c7a84 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,7 +2,6 @@ const compareVersions = require("compare-versions"); const http = require('https'); const {URL} = require('url'); const repositoryBuildDefinition = require('./type/repository-build-definition'); -const packagesConfig = require("./build-config/packages-config"); /** * If a and b are the same, return 0. Return pos number if a > b, or neg number if a < b