Versioning code in two separate projects concurently with subverison - php

I have a need to create a library of Object Oriented PHP code that will see much reuse and aspires to be highly flexible and modular. Because of its independent nature I would like it to exist as its own SVN project.
I would like to be able to create a new web project, save it in SVN as its own separate project, and include within it the library project code as well. During this process, while coding the web application code and making commits, I may need to add a class to the library. I would like to be able to do so and commit those changes back to the libraries project code.
In light of all this I could manage the code in two ways
Commit the changes to the library back to a branch of its original base project code and make the branch name relevant to the web project I was using it with
Commit the changes to the library back to the original code, growing it in size regardless of any specific references that might exist.
I have two questions
How can I include this library project code into a new project yet not break the subversion functionality, i.e. allowing me to make changes to each project individually?
How I can keep the code synchronized? If I choose the first method of managing the library code I may want to grab changes from another branch and pull it in for use in another.
EDIT - I realize I can simply check out these projects individually and commit/update them individually as well, but then how can I include them together as a single project? To be more clear, how could I create a web project that includes the library code as a unified subversion project in consideration of the points I elaborated on above?

I think you can use svn:externals to achieve what you want. It will pull the library project into your website project and update it whenever you update your working copy. The only thing is you cannot commit back to the library in the same commit as you project as described in this question How do I checkin to local copy AND svn:externals subdirectories in one commit?.

Option #1 looks like the right way to go.
I think you should expect to keep separate branches of the API project for any of your sites that have site-specific modifications to the shared API. Of course, you don't need to create the branch upfront, just checkout the 'trunk' and make sure you branch before you commit any site-specific changes.
There are a couple of articles on branching/merging that I have used in the past that might help you out:
Streamed Lines: Branching Patterns for Parallel Software Development
MSDN Branching and Merging Primer
However, there are some aspects of your 'two questions' that are a bit confusing/concerning. Hopefully I'm misinterpretting what you've said, but keep the following in mind:
With your first question, I think you might be getting caught up on the physical location of the source code on your development machine and how your repositories will be structured (hint: treat the two separately).
In your second question, you mention specific references and it sounds like you might be thinking of making your API in some way dependent on the website source (hint: bad idea for an API).

Related

How to make a git branch with only specific/selected files from a PHP project?

I'm a total newbie to this Git.
My PHP project files have been added to Git by admin.
Now one new person is going to start working on this project. He will work on one module of this project. So, being a senior developer I've been asked to create a branch for him that will contain only specific files that he will need to start work on the specific module.
So this thing has created so many questions in my mind :
Can I create a special branch for him with only specific/selected files from the project? If yes, how? If no, why?
Now only master branch of project is present. If the new branch of git is created for the new developer and he commits and pushes the changes he made to the git; how will they get merged with the master branch? Do I need to do it manually using third party tool like 'DeployHQ' or anything like or is there any way around.
To keep the things easy for him what I want to do is he should be able to commit, push the changes, those changes would straight away be reflected on server and he should be able to check it by running the pages in a browser. Can I make the this simple and easy as I'm thinking.
In a nutshell I don't want to disclose all of my project files to him and want to keep things easier and simpler for me as well as for him.
Please please please guide me.
Thanks.
The basic building block of GIT version control is project. You can't branch off only some files from the master as it doesn't make any sense in an environment where projects are the single version controlled entities.
You can add or remove files from a branch and later commit to the master with the changes.
Some people refer to the branching model in Git as its “killer
feature” , and it certainly sets Git apart in the VCS community. Why
is it so special? The way Git branches is incredibly lightweight,
making branching operations nearly instantaneous and switching back
and forth between branches generally just as fast. Unlike many other
VCSs, Git encourages a workflow that branches and merges often, even
multiple times in a day. Understanding and mastering this feature
gives you a powerful and unique tool and can literally change the way
that you develop.

Include methods into class

My colleague and me are both working in a MVC system on the same controller. Problem is that we can't edit the same file at the same time because we're overwriting each others changes.
Is there a way to include methods into a class using the include() function?
Basically I want three files, controller.php his_file.php and my_file.php
U need a Versioning System like SVN to handle this conflicts and code loss or need a centralised system where you and ur colleague must place code after taking the latest code from each other, thats what versioning system do generally... you dont have to add any extra code load to acheive what you need this which would be again a bad practice.
As a single user the main advantages are
Automatic backups: If you accidentally delete some file (or part of
a file) you can undelete it. If you change something and want to
undo it, the VCS can do so.
Sharing on multiple computers: VCSes are designed to help multiple people collaboratively edit text files. This makes sharing between multiple computers (say your desktop and laptop) particularly easy. You do not need to bother if you always copied the newest version; the VCS will do that for you. Even if you are offline and change files on both computers, the VCS will merge the changes intelligently once you are online.
Version control and branching: Say you published some class notes as
a pdf and want to fix some typos in them while simultaneously
working on the notes for next year. No problem. And you only need to
fix the typos once, the VCS will merge them to the other versions.
Tagging.
Working with collaborators even if they don't have the
VCS themselves. I can make a branch copy for my collaborator on my
own system and simply copy in their corrections to that each time,
then merge them into the main branch as if they'd been using the VCS
all along. Keeps the advantages of using version control but without
requiring all collaborators to use it.
Maintaining different versions.
If you have multiple people working on the same files you will want to use a revision control system like SVN, GIT, Mercurial or even CVS and then merge changes at the end of the day:
Revision control, also known as version control and source control (and an aspect of software configuration management), is the management of changes to documents, programs, large web sites and other information stored as computer files. It is most commonly used in software development, where a team of people may change the same files. Changes are usually identified by a number or letter code, termed the "revision number", "revision level", or simply "revision". For example, an initial set of files is "revision 1". When the first change is made, the resulting set is "revision 2", and so on. Each revision is associated with a timestamp and the person making the change. Revisions can be compared, restored, and with some types of files, merged.
As for
Is there a way to include methods into a class using the include() function?"
see my answer to
Can I include code into a PHP class?

How to configure subversion, for web application development, to limit developer access to source code

My team has been working on a web application based on php, msql for backend and html,css,jquery for front end. We have been working for quite sometime now without version control. The project has become quite large and complicated now and feel that it is time to use some sort of version control ( vc ).
We have been reading quite a lot about vc and have found several techniques that people have suggested. although it might be a perfect method for them. it does not effectively apply to our case.
our application is split up into various modules and we have outsourced work to a few freelancers. freelancers work independently over front end or back end depending on their skill. The work has been happening over a Private Network so far and we would like to shift to an online system.
Now the problem is that we cannot distribute the source code for the entire project to all developers. developers are only allowed to work on some common libraries and their respective modules.
Hence we cannot allow the entire project to be downloaded onto each developers Local machine. Thus we need to find a way for all developers to be working on the same branch OR on the trunk. to be able to access only certain sections of the code and on saves/commits be able to check how their changes have effected instantly.
Is there a way the above task can be achieved ? for a web application ? using a version control like subversion?
To summarize, the features we are trying to implement are as follows.
Instant effects on save/commit ( When each developer saves/commits they should be able to test the effects like normal through the browser instantly )
Limited access ( Each developer can access only a specific part of the project and not the whole project. )
Online repository / Online copy - ( we are working on a VPN connection, and would like to have the website work on an online copy. so when a commit is made, the developer can view his changes online instead of the VPN )
after a lot of searching online we were able to find the below possibilities. But not sure if it is the right way to go.
For instant effects --> Entire system is checked out in a webroot folder ( eg. wamp/www/projectName ), a bat file is called to update the current system in the webroot, everytime a commit is made, by using the post-commit hook.
Limited access --> All development for all developers happen in the trunk OR a Development branch, developers can access their respective sections, lock it if needed and commit changes when they are ready to see its effects ( note still in dev branch ).
tags are created whenever a stable release is created. these Tagged copies are never modified.
Is such a configuration achievable using subversion or should we look at other open-source version control tools ?
Trying to prevent devs from accessing the entire source tree seems a bit misguided to me. Is it company politics? Don't you trust your developers?
In any case..
The easiest way to achieve what you want would probably be to put each module into its own repository (svn, git, whatever). Then you can selectively choose who has access to which repo.
Post-commit hook, which unconditionally "do site" is in a common not-so-good idea: developer can commit semi-finished code and even don't think about testing it
Make your Working Copy public, when site became public - not-so-good idea from the POV of security and IP. For SVN 1.7 to move WC-root outside web-root is much better idea
If modules are splitted to different directories, you can create repository per module and "super-repository", which, with svn:externals, combine repositories in Project
Path-access inside tree can be easy controlled (in http-repo) by authz_svn_module
Enable creating private personal short-time branches for developers ("shelves"), it helps to avoid (with 1) huge messed up commits
Firstly, I'd recommend reading the "Continuous Delivery" book (website here). It provides many examples for how to set up this kind of thing.
Secondly, yes, SVN allows you to assign permissions on a folder level as well as repo level (but read the "do you really want to do this" section).
Thirdly, making sure developers have up to date copies is something you should instill by discipline - "before starting work, and before committing, run svn update"). Post-commit hooks have a nasty habit of breaking stuff, and you're not preventing commits which break the build.
Fourthly, I'd consider setting up a continuous integration server (also described in the Continuous Delivery book). This makes sure you have a clean, working build whenever you put together the work of your developers.

svn - 2 'packages' one using elements of the other, best way to structure this?

I have what I believe is a tricky situation but this usually indicates I'm ignorant of something quite simple.
I currently have one php project that is in an svn repo, call it 'firstproject'. The working copy of this is an apache virtual host dir so I can happily run this project at any point of development through a browser.
I now have another project 'newproject' that I want to use some of the core code of 'firstproject' but when newproject requires me to refactor parts of the firstproject classes I would like for that to be integrated back into firstproject at some point.
Is there any way to set svn up so I can have a working copy of newproject happily in it's own apache virtual host and comprising some code from firstproject and then its own code and for svn to keep tabs on which is which or is it a case of creating a 'newproject' branch of firstproject, editing away adding the newproject code and then doing some sort of merging of code back into 'firstproject' when it seems appropriate?
Many thanks to anyone who can help me thinking about this, it feels like there should be a neat way but maybe there isn't.
It seems to me that firstproject should release some deliverable (a library). newproject can then consume this.
If that library needs to change, then the changes should be made in firstproject, and released.
That's how I'd normally manage this sort of dependency in a non-PHP world. I'm not sure that in PHP it should/would be any different. It's a bit of a headache, but you're building a reusable library that a downstream project can consume (and choose which version it consumes, note).
If there is a large part of the code that is common, then you can consider using a common repository instead of two seperate repositories for these two projects. You can then take out a branch for the code that might change within the project newproject . The workspace on the newproject apache server will have to be from this branch so that any changes can be committed back to the branch and merged back to the trunk when you are ready. This way you can incorporate the changes back to the firstproject mainline/trunk.
You can also explore svn externals for another approach to mix and match if you need a workspace with checkouts from multiple repositories. I have not implemented this myself but you may find the details here:
http://svnbook.red-bean.com/en/1.1/ch07s04.html

How to efficiently manage multiple installations of a web application?

From my experience, one of the bigger problems we come across during our webdevelopment process is keeping different setups updated and secure across different servers.
My company has it's own CMS which is currently installed across 100+ servers. At the moment, we use a hack-ish FTP-based approach, combined with upgrade scripts at specific locations to upgrade all of our CMS setups. Efficiently managing these setups becomes increasingly difficult and risky when there are several custom modules involved.
What is the best way to keep multiple setups of a web application secure and up-to-date?
How do you do it?
Are there any specific tips regarding modularity in applications, in order to maintain flexibility towards our clients, but still being able to efficiently manage multiple "branches" of an application?
Some contextual information: we mainly develop on the LAMP-stack. One of the main factors that helps us sell our CMS is that we can plugin pretty much anything our client wants. This can very from 10 to to 10.000 lines of custom code.
A lot of custom work consists of very small pieces of code; managing all these small pieces of code in Subversion seems quite tedious and inefficient to me (since we deliver around 2 websites every week, this would result in a lot of branches).
If there is something I am overlooking, I'd love to hear it from you.
Thanks in advance.
Roundup: first of all, thanks for all of your answers. All of these are really helpful.
I will most likely use a SVN-based approach, which makes benlumley's solution closest to what I will use. Since the answer to this question might differ in other usecases, I will accept the answer with the most votes at the end of the run.
Please examine the answers and vote for the ones that you think have the most added value.
I think using a version control system and "branching" the part of the codes that you have to modify could turn out to be the best approach in terms of robustness and efficiency.
A distributed version system could be best suited to your needs, since it would allow you to update your "core" features seamlessly on different "branches" while keeping some changes local if need be.
Edit: I'm pretty sure that keeping all that up to date with a distributed version system would be far less tedious than what you seem to expect : you can keep the changes you are sure you're never going to need elsewhere local, and the distributed aspect means each of your deployed application is actually independent from the others and only the fix you mean to propagate will propagate.
If customizing your application involves changing many little pieces of code, this may be a sign that your application's design is flawed. Your application should have a set of stable core code, extensibility points for custom libraries to plug into, the ability to change appearance using templates, and the ability to change behavior and install plugins using configuration files. In this way, you don't need a separate SVN branch for every client. Rather, keep the core code and extension plugin libraries in source control as normal. In another repository, create a folder for each client and keep all their templates and configuration files there.
For now, creating SVN branches may be the only solution that helps you keep your sanity. In your current state, it's almost inevitable that you'll make a mistake and mess up a client's site. At least with branches you are guaranteed to have a stable code base for each client. The only gotcha with SVN branches is if you move or rename a file in a branch, it's impossible to merge that change back down to the trunk (you'd have to do it manually).
Good luck!
EDIT: For an example of a well-designed application using all the principles I outlined above, see Magento E-Commerce. Magento is the most powerful, extensible and easy to customize web application I've worked with so far.
I may be wrong, but it seems to me what Aron is after is not version control. Versioning is great, and I'm sure they're using it already, but for managing updates on hundreds of customized installations, you need something else.
I'm thinking something along the lines of a purpose-built package system. You'll want every version of a module to keep track of its individual dependencies and 'guaranteed compatibilities', and use this information to automatically update only the 'safe' modules.
E.g. let's say you've built a new version 3 of your 'Wiki' module. You want to propagate the new version to all the servers running your application, but you've made changes to one of the interfaces within the Wiki module since version 2. Now, for all default installations, that is no problem, but it would break installations with custom extensions on top of the old interface. A well-planned package system would take care of this.
To address the security question, you should look into using digital signatures on your patches. There are lots of good libraries available for public-key-based signatures, so just go with whatever seems to be the standard for your chosen platform.
Not sure whether someone's said this, there are a lot of long responses here, and I've not read them all.
I think a better approach to your version control would be to have your CMS sat on its own in its own repository and each project in its own. (or, all of these could be subfolders within one repo i guess)
You can then use its trunk (or a specific branch/tag if you prefer) as an svn:external in each project that requires it. This way, any updates you make to the CMS can be committed back to its repository, and will be pulled into other projects as and when they are svn updated (or the external is svn:switch 'ed).
As part of making this easier, you will need to make sure the CMS and the custom functionality sit in different folders, so that svn externals works properly.
IE:
project
project/cms <-- cms here, via svn external
project/lib <-- custom bits here
project/www <-- folder to point apache/iis at
(you could have cms and lib under the www folder if needed)
This will let you branch/tag each project as you wish. You can also switch the svn:external location on a per branch/tag basis.
In terms of getting changes live, I'd suggest that you immediately get rid of ftp and use rsync or svn checkout/exports. Both work well, the choice is up to you.
I've got most experience with the rsync route, rsyncing an svn export to the server. If you go down this route, write some shell scripts, and you can create a test shell script to show you the files it will upload without uploading them as well, using the -n flag. I generally use a pair of scripts for each environment - one a test, and one to actually do it.
Shared key authentication so you don't need a password to send uploads up may also be useful, depending on how secure the server to be given the access is.
You could also maintain another shell script for doing bulk upgrades, which simply calls the relevant shell script for each project you want to upgrade.
Have you looked at Drupal? No, not to deploy and replace what you have, but to see how they handle customizations and site-specific modules?
Basically, there's a "sites" folder which has a directory for every site you're hosting. Within each folder is a separate settings.php which allows you to specify a different database. Finally, you can (optionally) have "themes" and "modules" folders within sites.
This allows you to do site-specific customizations of particular modules and limit certain modules to those sites. As a result, you end up with a site that the vast majority of everything is perfectly identical and only the differences get duplicated. Combine that with the way it handles upgrades and updates and you might have a viable model.
Build into the code a self-updating process.
It will check for updates and run them when/where/how you have configured it for the client.
You will have to create some sort of a list of modules (custom or not) that need to be tested with the new build prior to roll-out. When deploying an update you will have to ensure these are tested and integrated correctly. Hopefully your design can handle this.
Updates are ideally a few key steps.
a) Backup so you can back out. You should be able to back out
the entire update at any time. So,
that means creating a local archive
of the application and database
first.
b) Update Monitoring Process - Have the CMS system phone home to look for a new build.
c) Schedule Update on availability - Chances are you don't want the update to run the second it is available. This means you will have to create a cron/agent of some kind to do the system update automatically in the middle of the night. You can also consider client requirements to update on weekends, or on specific days. You can also stagger rolling out your updates so you don't update 1000 clients in 1 day and get tech support hell. Staggered roll-out of some kind might be beneficial for you.
d) Add maintenance mode to update the site -- Kick the site into maintenance mode.
e) SVN checkout or downloadable packages -- ideally you can deploy via svn checkout, and if not, setup your server to deliver svn generated packages into an archive that can be deployed on client sites.
f) Deploy DB Scripts - Backup the databases, update them, populate them
g) Update site code - All this work for one step.
h) Run some tests on it. If your code has self-tests built in, it would be ideal.
Here's what I do...
Client-specific include path
Shared, common code is in shared/current_version/lib/
Site specific code is in clients/foo.com/lib
The include path is set to include from the clients/foo.com/lib, and then share/lib
The whole thing is in a version control system
This ensures that the code uses shared files wherever possible, but if I need to override a particular class or file for some reason, I can write a client specific version in their folder.
Alias common files
My virtual host configuration will contain a line like
Alias /common <path>/shared/current_version/public_html/common
Which allows common UI elements, icons, etc to be shared across projects
Tag the common code with each site release
After each site release, I tag the common code by creating a branch to effectively freeze that point in time. This allows me to deploy /shared/version_xyz/ to the live server. Then I can have a virtual host use a particular version of the common files, or leave it pointing at the current_version if I want it to pick up the latest updates.
Have you looked at tools such as Puppet (for system administration incl. app deployment) or Capistrano (deployment of apps in RubyOnRails but not limited to these)?
One option would be to set up a read-only version control system (Subversion). You could integrate access to the repository into your CMS and invoke the updates through a menu, or automatically if you do not want the user to have a choice about an update (could be critical). Using a version control system would also allow you to keep different branches easily
As people have already mentioned that using version control (I prefer Subversion due to functionality) and branching would be the best option. Another open source software available on sourceforge called cruisecontrol. Its amazing, you configure cruisecontrol with subversion in sach a way that any code modification or new code added in serversion, Cruise control will know automatically and will do build for you. It will save your hell of time.
I have done the same way in my company. we have four projects and have to deploy that project on different servers. I have setup cruiseconrol in such a way that any modification in code base triggers automatic build. and another script will deploy that build on the server. your are good to go.
If you use a LAMP stack I would definitely turn the solutions files into a package of your distribution and use it for propagate changes. I recommend for that matter Redhat/Fedora because of RPM and it's what I have experience on. Anyway you can use any Debian based distribution too.
Sometime ago I made a LAMP solution for managing an ISP hosting servers. They had multiple servers to take care of web hosting and I needed a way to deploy the changes of my manager, because every machine was self-contained and had a online manager. I made a RPM package containing the solution files (php mostly) and some deploying scripts that runned with the RPM.
For automated updating we had our own RPM repository set on every server in yum.conf. I set an crontab job to update the servers daily with the latest RPMs from that trusted repository.
Trustiness can be achieve too because you can use trust settings in the RPM packages, like signing them with your public key file and accepting only signed packages.
Hm could it be an idea to add configuration files? You wrote that a lot of small script are doing something. Now if you'd build them into the sources and steered them with configuration files shouldn't that "ease" that?
On the other hand having branches for every customer looks like an exponential growth to me. And how would you "know" which areas you've done something and do not forget to "make" changes in all other branches also. That looks quite ugly to me.
It seems a combination of revision controls, configuration options and/or deployment receipts seems to be a "good" idea.....
With that many variations on your core software, I think you really need a version control system to stay on top of pushing updates from the trunk to the individual client sites.
So if you think Subversion would be tedious, you've got a good sense for what the pain points will be... Personally, I wouldn't recommend Subversion for this, since it's not really that good at managing & tracking branches. Although benlumley's suggestion to use externals for your core software is a good one, this breaks down if you need to tweak the core code for your client sites.
Look into Git for version control, it's built for branching, and it's fast.
Check out Capistrano for managing your deployments. It's a ruby script, often used with Rails, but it can be used for all sorts of file management on remote servers, even non-ruby sites. It can get the content to the remote end through various stragegies including ftp, scp, rsync, as well as automatically checking out the latest version from your repository. The nice features it provides include callback hooks for every step of the deploy process (e.g. so you can copy your site-specific configuration files which might not be in version control), and a release log system--done through symlinks--so you can quickly roll back to a previous release in case of trouble.
I'd recommend a config file with the list of branches and their hosted location, then run through that with a script that checks out each branch in turn and uploads the latest changes. This could be cron'd to do nightly updates automatically.

Categories