Open lukeholder opened 11 years ago
I agree a convention would be nice, especially for straightupcraft & the plugin store.
As you can see I currently have my build scripts in a sub folder of the plugin, this folder is excluded when running the build process. This sure isn't the best way to do it, but it works for me.
I've looked at your project structure and I think there is a considerable problem because you can't have multiple git tracked plugins in the same Craft install. Or am I missing something?
Anyway, I'm really looking forward to your blog article.
I like having the plugins/pluginname within the repo also, because it explains where to install the plugin for noobs.
Interesting thought on the git location - would have thought you would not want to include your whole git history in your distributed plugin so keeping it one level above it better? This would also enable tracking your build scripts and developer readme
so my ideal would be below but would love to iterate on this with you:
craft-example
├── .git
├── buildscript
├── plugin
│ └── example
│ ├── composer.json
│ ├── controllers
│ ├── elemnttypes
│ ├── examplePlugin.php
│ ├── fieldtypes
│ ├── helpers
│ ├── migrations
│ ├── models
│ ├── plugin.json
│ ├── records
│ ├── services
│ ├── templates
│ ├── variables
│ ├── vendor
│ └── widgets
└── readme.md
Assuming that 'buildscript' is not something you'd even want to include when distributing your plugin (outside of GitHub), you might find it better in the long run if you put a "Source" folder at the root of your repo, which contains all of the distributable files. For example Craft’s own repo is organized like this:
Craft/
Build/ (a .gitignore’d folder that is the default location for our build script)
Resources/ (where we keep internal dev resources like a Yii hack log)
Source/ (all of the actual source files)
Utils/ (any utilities we've written for ourselves, like the build script and translation scraper)
README.md
As those non-Source folders inevitably add up, keeping all source files tucked away in a Source folder becomes more and more worth it. Especially because it simplifies the build script itself.
The structure within the Source folder is really a discussion of what you want your distributable package to be. I like Luke’s idea of distributing an actual “plugins” folder, with the “example” folder within it, and all of the actual plugin files within that. There‘s no room for confusion there.
I'll add my 2 cents here as well.
About the git location and the git history in the distributed plugin: I'm using Phing (I must admit I've started using it just 2 weeks ago) to build the distributed plugins and it automatically remove any VCS files.
My current build script does the following (let's say the plugin is called Foo):
And then I have a zip file which contains the plugin folder, so that if you unzip it in craft/plugins you get the folder craft/plugins/foo/ and you're ready to go. The reason I did it this way is because I wanted to be able to develop and test without having to rebuild the project every time.
As for the help for new users to place their plugins, I hope this will become trivial with the plugin store.
To conclude I would really like the following structure which is very similar to Craft's:
foo/
├── .git/
├── bin/ (distributable files)
├── docs/ (documentation, changelog...)
├── utils/ (build scripts, doc generator and more...)
├── vendor/ (especially for composer packages as they are not part of the plugin's source)
├── src/ (the plugin's source)
| ├── controllers/
| ├── fieldtypes/
| ├── services/
| ├── variables/
| ├── ...
| └── FooPlugin.php
├── composer.json
├── .gitignore (ignore vendor/ and bin/)
└── README.md
But the problem I had with this structure is that I had to symlink from my craft/plugins/ folder to the foo/src (leading to path problems with the vendor/ folder), or build everytime. This became too overwhelming so I switched to what I do now.
I really like the structure proposed by @lukeholder and I think @builtbysplash makes a very valid point regarding developer workflow (design, test, distribute, etc) because symlinking just isn't practical and there should be something structured enough for consistency but flexible enough to be suitable/approachable for those getting started in plugin development but robust enough to have the proper setup for unit testing, composer, building, etc.
Definitely a topic worth discussing further, I'm in!
Just want to clarify, this discussion is about the layout of a standardized plugin development project structure - not the distributable. having all plugins on github be named with a preceding "craft-" will really assist people searching.
@brandonkelly the buildscript, or the things in your build directory, would be a part of the git repo since you will be distributing the build scripts to other developers. The buildscript would obviously not include it's self in the creation of the distributable .zip file, you are right, that would only be what is in the source/ directory.
If you are using composer to manage dependancies you would want to gitignore the vendor\ directory but commit your composer.json and composer.lock. This will enable other developers to work with the locked versions of the dependancies on certain branches.
The vendor directory will be included in the build through the build script, but the build script should not include the composer.json and composer.lock as end user will have the vendor'd dependancies for that build and will not be running composer over the project.
Again, we do need those 2 files in the repo to other developers can do a composer install
to get the dependancies.
I would suggest the composer.json and the composer.lock live at the top level, but in order to get the vendor folder (that composer would install all the dependancies into) live inside the Source folder, you just need to set the config in the composer.json:
{
"config": {
"vendor-dir": "source/plugin/vendor"
}
}
This really makes it easy for the build script as all the code is inside the source folder:
I agree with @brandonkelly to have a source/ or src/ folder that contains all code. Anything else above that is developer related.
So revised I have:
craft-example
├── .git
├── .gitignore (ignoring vendor/)
├── README.md
├── utils\
├── build\
├── composer.json
├── composer.lock
├── resources\
└── source\
└── plugin\
└── example\
├── controllers\
├── elemnttypes\
├── examplePlugin.php
├── fieldtypes\
├── helpers\
├── migrations\
├── models\
├── plugin.json (LOOKING FORWARD TO THIS BRANDON)
├── records\
├── services\
├── templates\
├── variables\
├── vendor\
└── widgets\
Please bring more discussion. Standardizing this will have a huge impact of getting craft developers writing and collaborating better on code.
After we have all agreed I will be writing up the spec and also build a new example plugin like adrian macneil did (its out of date and broken in some places)
A further various points on symlinking - I don't see a better, more efficient way during development of a plugin. Please enlighten me if there is a better way.
It's looking good Luke, I was going to ask about symlinking but then I saw your comment. It also makes sense to have vendor in the source folder to avoid problems when symlinking.
The only thing I don't understand is why you have two subfolder in source/ to get to the actual source of the plugin. Is there something important I'm missing?
@builtbysplash the source folder houses all your plugin code. You are right, having the plugin/ folder is superfluous during development, but makes sense when we build the plugin for distribution with the contents of the source/ folder. The end user will get a zip folder that looks like this:
example.zip
└── plugin\
└── example\
├── controllers\
├── elemnttypes\
...
What this does is give a clear explanation to the user of the plugin where to place the example folder within craft (the plugin folder)
It is not a big deal, but a useful convention set out by plugins from other CMS's.
Yes, we could have the buildscript create this directory when creating the zip, but this simplifies the buildscript.
In my opinion, this should be the job of the buildscript, it's easy enough to create the 2 subfolders during the build process.
The users shouldn't have to place the directories directly from the zip because they will be available in the plugin store. Now the question is what structure and format we will have to use for the plugin store?
Most likely the Plugin Store will just want a zip of your actual plugin folder. TBD though.
Looking at writing an open source craft project layout convention.
It is great that you have named the project craft- in the github repo, but could you nest the plugin files in a plugin folder under a folder called 'detect'
example:
https://github.com/lukeholder/craft-inflect
This enables you to have developer level files that could include build scripts etc as well as developer level README.
I will write a public a blog article about this shortly.