Multi-Project Issue Tracking With Producer

With Producer, you can get a list of the open issues from your remote origin by running producer issues from the project repository:

$ cd ~/Code/radarphp/Radar.Adr
$ producer issues

    14. Separate Package for ResponderAcceptsInterface?

    29. Service level actions?


However, I’m the lead on about 40 different packages and projects, and at one point or another many of them have issues to be tracked on Github. It’s tedious to go to each package repository to list its issues separately. I want to be able to see a list of all issues on all my projects; then I can review them all at once to see what gets my attention.

To get a list of all open issues on several projects, you can create a bash script that changes to each project directory and runs project issues in each one:

cd ~/Code/atlasphp/Atlas.Cli; producer issues;
cd ~/Code/atlasphp/Atlas.Orm; producer issues;
cd ~/Code/auraphp/Aura.Accept; producer issues;
; ...
cd ~/Code/radarphp/Radar.Project; producer issues;
cd ~/Code/relayphp/Relay.Relay; producer issues;
cd ~/Code/relayphp/Relay.Middleware; producer issues;

Call the script, make it executable with chmod +x, and then you can issue ./ to get a list of all open issues on all your projects. Pipe the result to a file for easy viewing if you like!

Producer 2.0.0 Released!

Just a short note to say that most (all?) of the feedback from last month’s inital release of Producer has been incorporated into today’s 2.0.0 stable release!

The major changes are:

  • You are no longer required to install Producer globally. You can now install it as a require-dev in your project and call it as ./vendor/bin/producer. (Personally, I prefer to have it global, but that’s mostly because I manage so many different libraries.)

  • Along with that, Producer now recognizes a project-specific .producer/config file so you can override Producer settings on a per-project basis.

  • Finally, Producer does not install phpunit and phpdoc any more. You will need to install them yourself, either globally or as part of your package. The benefit here is that you can now specify custom paths to phpunit and phpdoc commands in your .producer/config file.

(Producer is a command-line quality-assurance tool to validate, and then release, your PHP library package. It supports Git and Mercurial for version control, as well as Github, Gitlab, and Bitbucket for remote origins.)

Empirical Research On Software-Engineering Myths

(Heavily condensed from the original, which you should read in its entirety.)

More Isn’t Always Better: Higher code coverage was not the best measure of post-release failures in the field. If 99 percent of the code has been tested, but the 1 percent that did not get tested is what customers use the most, then there is a clear mismatch between usage and testing. It is more beneficial to achieve higher code coverage of more complex code than to test less complex code at an equivalent level. Those are the kinds of tradeoffs that development managers need to keep in mind.

Write Test Code First: TDD teams produced code that was 60 to 90 percent better in terms of defect density than non-TDD teams. They also discovered that TDD teams took longer to complete their projects—15 to 35 percent longer. “Over a development cycle of 12 months, 35 percent is another four months, which is huge. However, the tradeoff is that you reduce post-release maintenance costs significantly, since code quality is so much better. Again, these are decisions that managers have to make—where should they take the hit?”

Proving the Utility of Assertions: More assertions and code verifications means fewer bugs. Looking behind the straight statistical evidence, they also found a contextual variable: experience. Software engineers who were able to make productive use of assertions in their code base tended to be well-trained and experienced, a factor that contributed to the end results. What kind of action should development managers take based on these findings? The research team believes that enforcing the use of assertions would not work well; rather, there needs to be a culture of using assertions in order to produce the desired results.

Organizational Structure Does Matter – a Lot: Organizational metrics, which are not related to the code, can predict software failure-proneness with a precision and recall of 85 percent. This is a significantly higher precision than traditional metrics such as churn, complexity, or coverage that have been used until now to predict failure-proneness.

Geographical Distance Doesn’t Matter – Much: Most people preferred to talk to someone from their own organization 4,000 miles away rather than someone only five doors down the hall but from a different organization. Organizational cohesiveness played a bigger role than geographical distance.

Source: Exploding Software-Engineering Myths – Microsoft Research

PSR-7 and Session Cookies

One of the great things about PHP is its session handling capabilities. One call to session_start() and a huge amount of heavy lifting is done for you. It’s a great aid when writing page scripts.

However, as you start to need finer control over the HTTP response in your project, some of the automatic session behaviors begin to get in the way. In particular, when you are using PSR-7 to build your HTTP response, you realize that session_start() and session_regenerate_id() both automatically do the equivalent of calling setcookie() to write headers directly to the output. This means you cannot buffer those calls into the Response object for later sending.

How then can we use PHP’s session handling, when we want finer control over when and how cookies get sent?

The first trick is to tell PHP not to send a cookie when it does session work. This is accomplished with three ini_set() calls:

ini_set('session.use_trans_sid', false);
ini_set('session.use_cookies', false);
ini_set('session.use_only_cookies', true);

These direct PHP not to use transparent session IDs, not to use cookies, and (counterintuitively) to use only cookies. If I understand correctly, the combination of the last two means that PHP will read only from the cookies, and from nowhere else, to find the session ID value.

With those settings, a call to session_start() will cause PHP to read from the cookie values for the session ID, but it will not cause PHP to set any cookies for the session.

The second trick is to compare the session ID in the incoming request, to the session_id() value at the time you want to send the response. If they are different, that means a session has been started or regenerated, at which point you can send the session cookie manually. The following is an example Relay-compatible middleware that puts session cookie handling logic into effect:


When you examine the class, note that the cookie-creation code is intended to be the same as in the PHP session handling code itself. Note also that you can extract the relevant logic (“compare the Request session ID to the current one, and send a cookie if they’re different”) and use it in a non-middleware-based application.

With SessionHeadersHandler in place, subsequent middleware decorators can call session_start() and session_regenerate_id(), and PHP will no longer automatically write out a session cookie on its own. The handler will set the cookie into a PSR-7 Response object for later sending.

Unfortunately, this is only a partial solution for session headers. The handler does not deal with things like session cache expire and limiter headers. However, it does give you control over when session cookie itself get sent, and that’s a great aid when you want to work with PSR-7 Response objects.