{ "id": "122857", "key": "TIMOB-15806", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": { "id": "2", "description": "The problem described is an issue which will never be fixed.", "name": "Won't Fix" }, "resolutiondate": "2013-11-24T17:56:06.000+0000", "created": "2013-11-24T13:45:59.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "alloy", "cli", "compiler" ], "versions": [ { "id": "14982", "description": "Release 3.2.0", "name": "Release 3.2.0", "archived": false, "released": true, "releaseDate": "2013-12-19" } ], "issuelinks": [ { "id": "33344", "type": { "id": "10000", "name": "Blocks", "inward": "is blocked by", "outward": "blocks" }, "outwardIssue": { "id": "122846", "key": "ALOY-884", "fields": { "summary": "Errors removing orphaned sync adapters when using a widget-specific sync adapter", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "Critical", "id": "1" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } } ], "assignee": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "updated": "2017-03-22T21:30:06.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "13103", "name": "CLI", "description": "Node-based command line interface" } ], "description": "h2. update\r\n\r\nIt appears that this only really affects those using the titanium-bundle, as it adds an extra hook for the alloy process, thus causing it to fire twice. All Alloy projects contain their own plugin, so there's no need for anything Alloy-related to be in paths.hooks, otherwise we get problems like this.\r\n\r\n{code}\r\npaths.hooks = [\"/Users/tlukasavage/Development/node_modules/titanium-bundle/node_modules/alloy/hooks\"]\r\n{code}\r\n\r\nYou can see that more than one alloy plugin is found and used in the CLI output when you execute \"ti build -p ios\":\r\n\r\n{code}\r\n[DEBUG] Loaded plugin hooks:\r\n[DEBUG] /Users/tlukasavage/Development/node_modules/titanium-bundle/node_modules/alloy/hooks/alloy.js\r\n[DEBUG] /Users/tlukasavage/Development/node_modules/titanium-bundle/node_modules/titanium/hooks/tisdk3fixes.js\r\n[DEBUG] /Users/tlukasavage/Library/Application Support/Titanium/mobilesdk/osx/3.2.0/iphone/cli/hooks/install.js\r\n[DEBUG] /Users/tlukasavage/Library/Application Support/Titanium/mobilesdk/osx/3.2.0/iphone/cli/hooks/package.js\r\n[DEBUG] /Users/tlukasavage/Library/Application Support/Titanium/mobilesdk/osx/3.2.0/iphone/cli/hooks/run.js\r\n[DEBUG] /Users/tlukasavage/Development/twice/plugins/ti.alloy/hooks/alloy.js\r\n{code}\r\n\r\nDeleting the {{paths.hooks}} entry \"/Users/tlukasavage/Development/node_modules/titanium-bundle/node_modules/alloy/hooks\" causes everything to go back to working as normal. In the end, the titanium-bundle should not be installing hooks for Alloy, and the CLI should have some means of identifying that a hook has already run for the given build.\r\n\r\nh1. To reproduce\r\n\r\n{code:console}\r\nti create -p ios -n twice --id test.twice -d .\r\ncd twice\r\nalloy new\r\nti build -p ios\r\n{code}\r\n\r\nh1. Analysis\r\n\r\nIf you remove the Alloy plugin from {{tiapp.xml}} it solves the problem for the next build, but then the compiler itself will re-add the plugin, causing the next run to compile twice again.\r\n\r\n{code:xml}\r\n\r\n ti.alloy\r\n\r\n{code}\r\n\r\nh1. Log\r\nThe log showing the compile being done twice:\r\n\r\n{code:console}\r\n[INFO] Forcing rebuild: /Users/zandbergen/dev/tests/twice/build/iphone/build-manifest.json does not exist\r\n[INFO] Initiating prepare phase\r\n[INFO] Found Alloy app in /Users/zandbergen/dev/tests/twice/app\r\n[DEBUG] ----- CONFIGURATION -----\r\n[DEBUG] raw config = \"platform=ios,version=0,simtype=none,devicefamily=universal,deploytype=development\"\r\n[DEBUG] platform = ios\r\n[DEBUG] version = 0\r\n[DEBUG] simtype = none\r\n[DEBUG] devicefamily = universal\r\n[DEBUG] deploytype = development\r\n[DEBUG] project path = /Users/zandbergen/dev/tests/twice\r\n[DEBUG] app path = /Users/zandbergen/dev/tests/twice/app\r\n[DEBUG]\r\n[DEBUG] ----- CONFIG.JSON -----\r\n[DEBUG] {\r\n[DEBUG] \"dependencies\": {},\r\n[DEBUG] \"sourcemap\": true,\r\n[DEBUG] \"autoStyle\": false,\r\n[DEBUG] \"adapters\": [\r\n[DEBUG] \"localStorage\",\r\n[DEBUG] \"properties\",\r\n[DEBUG] \"sql\"\r\n[DEBUG] ]\r\n[DEBUG] }\r\n[DEBUG]\r\n[DEBUG] ----- CLEANING RESOURCES -----\r\n[DEBUG] Removing orphaned controllers...\r\n[DEBUG] Removing orphaned models...\r\n[DEBUG] Removing orphaned styles...\r\n[DEBUG] Removing orphaned sync adapters...\r\n[DEBUG] Removing orphaned assets and libs...\r\n[DEBUG]\r\n[DEBUG] ----- BASE RUNTIME FILES -----\r\n[TRACE] SRC_DIR=/Users/zandbergen/node_modules/titanium-bundle/node_modules/alloy/Alloy/lib\r\n[TRACE] Copying SRC_DIR/alloy.js --> Resources/iphone/alloy.js\r\n[TRACE] Copying SRC_DIR/alloy/backbone.js --> Resources/iphone/alloy/backbone.js\r\n[TRACE] Copying SRC_DIR/alloy/underscore.js --> Resources/iphone/alloy/underscore.js\r\n[TRACE] Copying SRC_DIR/alloy/widget.js --> Resources/iphone/alloy/widget.js\r\n[TRACE] Copying SRC_DIR/alloy/controllers/BaseController.js --> Resources/iphone/alloy/controllers/BaseController.js\r\n[TRACE] Copying SRC_DIR/alloy/sync/localStorage.js --> Resources/iphone/alloy/sync/localStorage.js\r\n[TRACE] Copying SRC_DIR/alloy/sync/properties.js --> Resources/iphone/alloy/sync/properties.js\r\n[TRACE] Copying SRC_DIR/alloy/sync/sql.js --> Resources/iphone/alloy/sync/sql.js\r\n[TRACE]\r\n[TRACE] SRC_DIR=/Users/zandbergen/node_modules/titanium-bundle/node_modules/alloy/Alloy/common\r\n[TRACE] Copying SRC_DIR/constants.js --> Resources/iphone/alloy/constants.js\r\n[TRACE]\r\n[TRACE] SRC_DIR=/Users/zandbergen/dev/tests/twice/app/assets\r\n[TRACE]\r\n[DEBUG]\r\n[INFO] ----- MVC GENERATION -----\r\n[INFO] [global style] loading from cache...\r\n[INFO] [index.xml] view processing...\r\n[INFO] style: \"index.tss\"\r\n[INFO] view: \"index.xml\"\r\n[INFO] controller: \"index.js\"\r\n[TRACE] - Processing \"builtins\" module...\r\n[TRACE] - Processing \"optimizer\" module...\r\n[TRACE] - Processing \"compress\" module...\r\n[INFO] created: \"Resources/iphone/alloy/controllers/index.js\"\r\n[DEBUG] map: \"build/map/Resources/iphone/alloy/controllers/index.js.map\"\r\n[INFO] created: \"Resources/iphone/alloy/styles/index.js\"\r\n[INFO]\r\n[INFO] [app.js] using cached app.js...\r\n[INFO]\r\n[INFO] ----- OPTIMIZING -----\r\n[INFO] - iphone/alloy.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[INFO] - iphone/alloy/sync/localStorage.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[INFO] - iphone/alloy/sync/properties.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[INFO] - iphone/alloy/sync/sql.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[TRACE]\r\n[TRACE] Benchmarking\r\n[TRACE] ------------\r\n[TRACE] [0.67619s] TOTAL\r\n[INFO]\r\n[INFO] Alloy compiled in 0.67619s\r\n[INFO] Found Alloy app in /Users/zandbergen/dev/tests/twice/app\r\n[INFO] Executing Alloy compile: /usr/local/bin/node /usr/local/bin/alloy compile /Users/zandbergen/dev/tests/twice/app --config platform=ios,version=0,simtype=none,devicefamily=universal,deploytype=development\r\n[DEBUG] .__ .__\r\n[DEBUG] _____ | | | | ____ ___.__.\r\n[DEBUG] \\__ \\ | | | | / _ < | |\r\n[DEBUG] / __ \\| |_| |_( <_> )___ |\r\n[DEBUG] (____ /____/____/\\____// ____|\r\n[DEBUG] \\/ \\/\r\n[DEBUG] Alloy 1.3.0 by Appcelerator. The MVC app framework for Titanium.\r\n[DEBUG]\r\n[DEBUG] ----- CONFIGURATION -----\r\n[DEBUG] raw config = \"platform=ios,version=0,simtype=none,devicefamily=universal,deploytype=development\"\r\n[DEBUG] platform = ios\r\n[DEBUG] version = 0\r\n[DEBUG] simtype = none\r\n[DEBUG] devicefamily = universal\r\n[DEBUG] deploytype = development\r\n[DEBUG] project path = /Users/zandbergen/dev/tests/twice\r\n[DEBUG] app path = /Users/zandbergen/dev/tests/twice/app\r\n[DEBUG]\r\n[DEBUG] ----- CONFIG.JSON -----\r\n[DEBUG] {\r\n[DEBUG] \"dependencies\": {},\r\n[DEBUG] \"sourcemap\": true,\r\n[DEBUG] \"autoStyle\": false,\r\n[DEBUG] \"adapters\": [\r\n[DEBUG] \"localStorage\",\r\n[DEBUG] \"properties\",\r\n[DEBUG] \"sql\"\r\n[DEBUG] ]\r\n[DEBUG] }\r\n[DEBUG]\r\n[DEBUG] ----- CLEANING RESOURCES -----\r\n[DEBUG] Removing orphaned controllers...\r\n[DEBUG] Removing orphaned models...\r\n[DEBUG] Removing orphaned styles...\r\n[DEBUG] Removing orphaned sync adapters...\r\n[DEBUG] Removing orphaned assets and libs...\r\n[DEBUG]\r\n[DEBUG] ----- BASE RUNTIME FILES -----\r\n[TRACE] SRC_DIR=/Users/zandbergen/node_modules/titanium-bundle/node_modules/alloy/Alloy/lib\r\n[TRACE] Copying SRC_DIR/alloy.js --> Resources/iphone/alloy.js\r\n[TRACE] Copying SRC_DIR/alloy/backbone.js --> Resources/iphone/alloy/backbone.js\r\n[TRACE] Copying SRC_DIR/alloy/underscore.js --> Resources/iphone/alloy/underscore.js\r\n[TRACE] Copying SRC_DIR/alloy/widget.js --> Resources/iphone/alloy/widget.js\r\n[TRACE] Copying SRC_DIR/alloy/controllers/BaseController.js --> Resources/iphone/alloy/controllers/BaseController.js\r\n[TRACE] Copying SRC_DIR/alloy/sync/localStorage.js --> Resources/iphone/alloy/sync/localStorage.js\r\n[TRACE] Copying SRC_DIR/alloy/sync/properties.js --> Resources/iphone/alloy/sync/properties.js\r\n[TRACE] Copying SRC_DIR/alloy/sync/sql.js --> Resources/iphone/alloy/sync/sql.js\r\n[TRACE]\r\n[TRACE] SRC_DIR=/Users/zandbergen/node_modules/titanium-bundle/node_modules/alloy/Alloy/common\r\n[TRACE] Copying SRC_DIR/constants.js --> Resources/iphone/alloy/constants.js\r\n[TRACE]\r\n[TRACE] SRC_DIR=/Users/zandbergen/dev/tests/twice/app/assets\r\n[TRACE]\r\n[DEBUG]\r\n[INFO] ----- MVC GENERATION -----\r\n[INFO] [global style] loading from cache...\r\n[INFO] [index.xml] view processing...\r\n[INFO] style: \"index.tss\"\r\n[INFO] view: \"index.xml\"\r\n[INFO] controller: \"index.js\"\r\n[TRACE] - Processing \"builtins\" module...\r\n[TRACE] - Processing \"optimizer\" module...\r\n[TRACE] - Processing \"compress\" module...\r\n[INFO] created: \"Resources/iphone/alloy/controllers/index.js\"\r\n[DEBUG] map: \"build/map/Resources/iphone/alloy/controllers/index.js.map\"\r\n[INFO] created: \"Resources/iphone/alloy/styles/index.js\"\r\n[INFO]\r\n[INFO] [app.js] using cached app.js...\r\n[INFO]\r\n[INFO] ----- OPTIMIZING -----\r\n[INFO] - iphone/alloy.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[INFO] - iphone/alloy/sync/localStorage.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[INFO] - iphone/alloy/sync/properties.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[INFO] - iphone/alloy/sync/sql.js\r\n[TRACE] processing \"builtins\" module...\r\n[TRACE] processing \"optimizer\" module...\r\n[TRACE] processing \"compress\" module...\r\n[TRACE]\r\n[TRACE] Benchmarking\r\n[TRACE] ------------\r\n[TRACE] [0.55402s] TOTAL\r\n[INFO]\r\n[INFO] Alloy compiled in 0.55402s\r\n[INFO] Alloy compiler completed successfully\r\n[INFO] Cleaning old build directory\r\n[INFO] Performing full rebuild\r\n[INFO] Copying Xcode iOS files\r\n[DEBUG] Copying /Users/zandbergen/Library/Application Support/Titanium/mobilesdk/osx/3.2.0.v20131122172908/iphone/Classes => /Users/zandbergen/dev/tests/twice/build/iphone/Classes\r\n{code}", "attachment": [], "flagged": false, "summary": "Alloy compiler runs twice when installed via titanium-bundle", "creator": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "subtasks": [], "reporter": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "environment": "CLI 3.2.0-alpha3\r\nAlloy 1.3.0-alpha3\r\nSDK 3.2.0.v20131122172908", "comment": { "comments": [ { "id": "280897", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "So it looks like the titanium-bundle is installing any hooks or commands it can find and them to the ti config. This is causing the Alloy hook to be fired twice. Once for the one in the project, once for the one that the titanium-bundle added. This is obviously not the desired behavior. \n\nI can hack titanium-bundle to not do this for Alloy, but a better long term solution would be for the CLI to be able to determine if 2 hooks have the same purpose, and when it has access to a global one versus a project-specific one, it should only fire the project specific one. \n\nh3. workaround\n\nExecute \"ti config\", find the extra path.hooks entry for alloy, and delete it.", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-11-24T15:31:40.000+0000", "updated": "2013-11-24T15:31:40.000+0000" }, { "id": "280900", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "As far as the CLI is concerned, a CLI plugin hook is just a JavaScript file. It has no idea what the JavaScript file is. There is no notion of a hook name/id or version. There's no way for the CLI to say \"hey, you already loaded the Alloy hook\" because it doesn't know what an Alloy hook is.\r\n\r\nSomeday we may add a name/id and version to each individual hook, but it would be optional.\r\n\r\nSince the Alloy hook knows how to identify itself, the Alloy hook should detect if there's already an Alloy hook loaded and if so, return. This can be done by referencing {{cli.hooks.loadedFilenames}} or maybe scanning {{cli.hooks.pre\\['build.pre.compile'\\]}} and {{cli.hooks.post\\['build.pre.compile'\\]}} for your callback functions.", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2013-11-24T17:56:06.000+0000", "updated": "2013-11-24T17:56:06.000+0000" }, { "id": "281078", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I think this should be the job of the CLI, via the means of id and version like you stated. It seems silly to push that responsibility out every single hook, rather than just solve the problem centrally in the CLI, especially when the workarounds you suggest AFAIK are undocumented. The issue in this ticket is addressed for the most part, but the underlying problem IMO needs to be addressed by the CLI, making it a bit more sensible when executing hooks that may be installed globally and locally to the current project.", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-11-24T23:24:29.000+0000", "updated": "2013-11-24T23:24:29.000+0000" }, { "id": "281080", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "Maybe the CLI will support it someday. That doesn't solve the problem today that there are plugin hooks in the wild that would not implement these ids and versions. Technically the old plugin system had the same problem. In the meantime, add yourself to the watch list for TIMOB-13847 and maybe it'll land in 3.2.1.", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2013-11-24T23:33:59.000+0000", "updated": "2013-11-24T23:33:59.000+0000" }, { "id": "281081", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "/me subscribed\n\nAnd that's fine if there's some on the wild that don't support the different format. That would be pretty trivial in the CLI to make the distinction between a string entry, which gets no validation, and an entry that is an object containing a name, version, etc... ", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-11-24T23:39:54.000+0000", "updated": "2013-11-24T23:39:54.000+0000" }, { "id": "415004", "author": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as Won't Fix.", "updateAuthor": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2017-03-22T21:30:06.000+0000", "updated": "2017-03-22T21:30:06.000+0000" } ], "maxResults": 7, "total": 7, "startAt": 0 } } }