Build site

This commit is contained in:
Oliver Davies 2017-07-10 22:28:39 +01:00
parent 6f8d067847
commit 0c7de8559a
743 changed files with 92961 additions and 0 deletions

View file

@ -0,0 +1,272 @@
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<title>2014 | Oliver Davies</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:url" content="https://www.oliverdavies.uk/blog/2015/03/20/2014">
<meta property="og:title" content="2014"/>
<meta property="og:image" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg"/>
<meta property="og:image:height" content="327"/>
<meta property="og:image:type" content="image/jpg">
<meta property="og:image:width" content="327"/>
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/main.css">
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/blog-post.css">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=57" sizes="57x57">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=114" sizes="114x114">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=72" sizes="72x72">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=144" sizes="144x144">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=60" sizes="60x60">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=120" sizes="120x120">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=76" sizes="76x76">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=152" sizes="152x152">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=160" sizes="160x160">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=96" sizes="96x96">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=32" sizes="32x32">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=16" sizes="16x16">
</head>
<body class="">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://www.oliverdavies.uk/">Oliver Davies</a>
</div>
<div id="navbar" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li class="">
<a href="/">About</a>
</li>
<li class="">
<a href="/experience">Experience</a>
</li>
<li class="">
<a href="/testimonials">Testimonials</a>
</li>
<li class="">
<a href="/talks">Talks</a>
</li>
<li class="active">
<a href="/blog">Blog</a>
</li>
<li class="">
<a href="/contact">Contact</a>
</li>
</ul>
</div> </div>
</nav>
<div class="container">
<div class="row">
<main class="col-md-9">
<h1>2014</h1>
<p class="posted">20th March 2015</p>
<p>A lot happened in 2014. Here are some of the main things that I'd like to highlight:</p>
<h2 id="joined-the-drupal-association">Joined the Drupal Association</h2>
<p>This was the main thing for me this year, in May I left <a href="http://precedent.com">Precedent</a> and joined the <a href="https://assoc.drupal.org">Drupal Association</a>. I work on the Engineering team, focused mainly on <a href="https://www.drupal.org">Drupal.org</a> but I've also done some theming work on the DrupalCon <a href="http://amsterdam2014.drupal.org">Amsterdam</a> and <a href="http://latinamerica2015.drupal.org">Latin America</a> websites, and some pre-launch work on <a href="https://jobs.drupal.org">Drupal Jobs</a>.</p>
<p>Some of the tasks that I've worked on so far are:</p>
<ul>
<li>Fixing remaining issues from the Drupal.org Drupal 7 upgrade.</li>
<li>Improving pages for <a href="https://www.drupal.org/supporters/partners">Supporting Partners</a>, <a href="https://www.drupal.org/supporters/technology">Technology Supporters</a> and <a href="https://www.drupal.org/supporters/hosting">Hosting Partners</a>. These previously were manually updated pages using HTML tables, which are now dynamic pages built with <a href="https://www.drupal.org/project/views">Views</a> using organisation nodes.</li>
<li>Configuring human-readable paths for user profiles using <a href="https://www.drupal.org/project/pathauto">Pathauto</a>. Only a small change, but made a big difference to end-users.</li>
<li>Migration of user data from profile values to fields, and various user profile improvements. This was great because now we can do things like reference mentors by their username and display their picture on your profile, as well as show lists of peope listing a user as their mentor. This, I think, adds a more personal element to Drupal.org because we can see the actual people and not just a list of names on a page.</li>
</ul>
<p>I've started keeping a list of tasks that I've been involved with on my <a href="/work/">Work</a> page, and will be adding more things as I work on them.</p>
<h3 id="portland">Portland</h3>
<p>I was able to travel to Portland, Oregon twice last year to meet with the rest of the Association staff. Both times I met new people and it was great to spend some work and social time with everyone, and it was great to have everyone together as a team.</p>
<h2 id="my-first-drupalcamp">My First DrupalCamp</h2>
<p>In February, I attended <a href="http://2014.drupalcamplondon.co.uk">DrupalCamp London</a>. This was my first time attending a Camp, and I managed to attend some great sessions as well as meet people who I'd never previously met in person. I was also a volunteer and speaker, where I talked about <a href="/blog/what-git-flow/">Git Flow</a> - a workflow for managing your Git projects.</p>
<p><p>
<blockquote class="twitter-tweet" data-cards="hidden" lang="en">
</p>
<p>Great presentation by <a href="https://twitter.com/opdavies">@opdavies</a> on git flow at <a href="https://twitter.com/search?q=%23dclondon&amp;src=hash">#dclondon</a> very well prepared and presented. <a href="http://t.co/tDINp2Nsbn">pic.twitter.com/tDINp2Nsbn</a></p>
<p>&mdash; Greg Franklin (@gfranklin) <a href="https://twitter.com/gfranklin/statuses/440104311276969984">March 2, 2014</a>
</blockquote>
</p>
</p>
<p>I was also able to do a little bit of sprinting whilst I was there, reviewing other people's modules and patches.</p>
<p>Attending this and <a href="https://prague2013.drupal.org">DrupalCon Prague</a> in 2013 have really opened my eyes to the face-to-face side of the Drupal community, and I plan on attending a lot more Camps and Cons in the future.</p>
<h2 id="drupalcon-amsterdam">DrupalCon Amsterdam</h2>
<p>I was also able to travel to Holland and attend <a href="https://amsterdam2014.drupal.org">DrupalCon Amsterdam</a> along with other members of Association staff.</p>
<h2 id="drupalcamp-bristol">DrupalCamp Bristol</h2>
<p>In October, we started planning for <a href="http://www.drupalcampbristol.co.uk">DrupalCamp Bristol</a>. I'm one of the founding Committee members,</p>
<p class="tags">
Tags:
<a href="https://www.oliverdavies.uk/blog/tags/drupal-association">drupal-association</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupalcamp-london">drupalcamp-london</a>, <a href="https://www.oliverdavies.uk/blog/tags/personal">personal</a> </p>
<div class="post-pager is-flex">
<div class="is-half">
<a href="/blog/2014/12/20/include-local-drupal-settings-file-environment-configuration-and-overrides">
&laquo; Include a Local Drupal Settings file for Environment Configuration and Overrides
</a>
</div>
<div class="is-half text-right">
<a href="/blog/2015/04/03/how-to-define-a-minimum-drupal-core-version">
How to Define a Minimum Drupal Core Version &raquo;
</a>
</div>
</div>
<div class="about-author">
<h2>About the Author</h2>
<img src="//images.oliverdavies.uk/assets/images/me-precedent.jpg" alt="Picture of Oliver" class="img-circle">
<p>Oliver Davies is a Web Developer, System Administrator and Drupal specialist based in the UK. He is a Senior Developer at <a href="https://microserve.io">Microserve</a> and also provides freelance consultancy services for Drupal websites, PHP applications and Linux servers.</p>
</div>
</main>
<div class="col-md-3">
<div class="panel badges text-center">
<a class="badge--da-member" href="https://assoc.drupal.org/membership" title="Im a Drupal Association member.">
<img
src="//images.oliverdavies.uk/assets/images/da-individual-member.png"
alt="Drupal Association Individual Member"
width="152"
>
</a>
<a href="http://drupalcores.com/#opdavies">
<img
alt="I built Drupal 8 with hand holding a wrench on blue background"
src="//images.oliverdavies.uk/assets/images/drupal-8.jpg"
/>
</a>
<img
src="//images.oliverdavies.uk/assets/images/badges/acquia-certified-developer-drupal-8.png"
alt="Acquia Certified Developer - Drupal 8 Exam Badge"
height="147" width="147"
/>
<a href="http://conference.phpnw.org.uk/phpnw17">
<img src="//images.oliverdavies.uk/assets/images/badges/phpnw17.png" alt="">
</a>
</div>
<div class="availability panel panel-default">
<div class="panel-heading">Availability</div>
<div class="panel-body">
<p>
<i class="fa fa-thumbs-o-up text-warning"></i>
Currently have limited part-time capacity
</p>
<p>
<i class="fa fa-thumbs-o-down text-danger"></i>
Currently no spare full-time capacity.
</p>
</div>
</div>
<div class="latest-posts panel panel-default">
<div class="latest-posts__heading panel-heading">Latest blog posts</div>
<ul class="list-group">
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot">
Introducing the Drupal Meetups Twitterbot
</a>
</span> -
<span class="post__date">9th June, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/20/turning-drupal-module-into-feature">
Turning Your Custom Drupal Module into a Feature
</a>
</span> -
<span class="post__date">20th May, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/15/drupalcamp-bristol-early-bird-tickets-sessions-sponsors">
DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
</a>
</span> -
<span class="post__date">15th May, 2017</span>
</li>
</ul>
</div>
</div>
</div> </div>
<footer class="container">
<p class="copyright">
&copy; 2010-2017 Oliver Davies. Built with <a href="https://sculpin.io">Sculpin</a>.
</p>
<div class="meetups">
<h2>Things that I organise</h2>
<ul>
<li class="meetups--drupal-bristol">
<a href="http://www.drupalbristol.org.uk" title="Drupal Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupal-bristol.jpeg" alt="Drupal Bristol">
</a>
</li>
<li class="meetups--drupalcamp-bristol">
<a href="http://www.drupalcampbristol.co.uk" title="DrupalCamp Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupalcamp-bristol.png" alt="DrupalCamp Bristol">
</a>
</li>
<li class="meetups--phpsw">
<a href="http://phpsw.uk" title="PHPSW">
<img src="//images.oliverdavies.uk/assets/images/meetups/phpsw.jpeg" alt="PHPSW">
</a>
</li>
</ul>
</div>
</footer>
<script src="https://www.oliverdavies.uk/assets/js/site.js"></script>
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11967257-1', 'auto'); ga('send', 'pageview');</script>
</body>
</html>

View file

@ -0,0 +1,290 @@
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<title>How to Define a Minimum Drupal Core Version | Oliver Davies</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:url" content="https://www.oliverdavies.uk/blog/2015/04/03/how-to-define-a-minimum-drupal-core-version">
<meta property="og:title" content="How to Define a Minimum Drupal Core Version"/>
<meta property="og:description" content="How to define a minimum Drupal core version for your module or theme."/>
<meta property="og:type" content="article"/>
<meta property="og:image" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg"/>
<meta property="og:image:height" content="327"/>
<meta property="og:image:type" content="image/jpg">
<meta property="og:image:width" content="327"/>
<meta name="twitter:card" content="summary"/>
<meta name="twitter:image:src" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg">
<meta name="twitter:creator" content="@opdavies"/>
<meta name="twitter:title" content="How to Define a Minimum Drupal Core Version"/>
<meta name="twitter:text:description" content="How to define a minimum Drupal core version for your module or theme."/>
<meta name="twitter:site" content="@opdavies"/>
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/main.css">
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/blog-post.css">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=57" sizes="57x57">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=114" sizes="114x114">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=72" sizes="72x72">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=144" sizes="144x144">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=60" sizes="60x60">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=120" sizes="120x120">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=76" sizes="76x76">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=152" sizes="152x152">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=160" sizes="160x160">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=96" sizes="96x96">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=32" sizes="32x32">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=16" sizes="16x16">
</head>
<body class="">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://www.oliverdavies.uk/">Oliver Davies</a>
</div>
<div id="navbar" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li class="">
<a href="/">About</a>
</li>
<li class="">
<a href="/experience">Experience</a>
</li>
<li class="">
<a href="/testimonials">Testimonials</a>
</li>
<li class="">
<a href="/talks">Talks</a>
</li>
<li class="active">
<a href="/blog">Blog</a>
</li>
<li class="">
<a href="/contact">Contact</a>
</li>
</ul>
</div> </div>
</nav>
<div class="container">
<div class="row">
<main class="col-md-9">
<h1>How to Define a Minimum Drupal Core Version</h1>
<p class="posted">3rd April 2015</p>
<p>This week, my first code patch was <a href="https://www.drupal.org/node/2394517#comment-9773143">committed to Drupal core</a>. The patch adds the <code>user_has_role()</code> function to the user module, to simplify the way to check whether a user in Drupal has been assigned a specific role. This is something that I normally write a custom function for each project, but it's now available in Drupal core as of <a href="https://www.drupal.org/drupal-7.36-release-notes">7.36</a>.</p>
<p>But what if someone is using a core version less than 7.36 and tries using the function? The site would return an error because that function wouldn't exist.</p>
<p>If you're building a new Drupal site, then I'd assume that you're using a latest version of core, or you have the opportunity to update it when needed. But what if you're writing a contrib module? How can you be sure that the correct minimum version of core?</p>
<h2 id="setting-dependencies">Setting Dependencies</h2>
<p>What I'm going to be doing for my contrib projects is defining a minimum version of Drupal core that the module is compatible with. If this dependency isn't met, the module won't be able to be enabled. This is done within your module's .info file.</p>
<h3 id="adding-a-simple-dependency">Adding a Simple Dependency</h3>
<p>You can define a simple dependency for your module by adding a line this this to your project's .info file:</p>
<pre><code class="language-bash">dependencies[] = views
</code></pre>
<p>This would make your module dependant on having the <a href="https://www.drupal.org/project/views">Views</a> module present and enabled, which you'd need if you were including views as part of your module, for example.</p>
<h3 id="adding-a-complex-dependency">Adding a Complex Dependency</h3>
<p>In the previous example, our module would enable if <em>any</em> version of Views was enabled, but we need to specify a specific version. We can do this by including version numbers within the dependencies field in the following format:</p>
<pre><code class="language-bash">dependencies[] = modulename (major.minor)
</code></pre>
<p>This can be a for a specific module release or a branch name:</p>
<pre><code class="language-bash">dependencies[] = modulename (1.0)
dependencies[] = modulename (1.x)
</code></pre>
<p>We can also use the following as part of the field for extra granularity:</p>
<ul>
<li>= or == equals (this is the default)</li>
<li>> greater than</li>
<li>&lt; lesser than</li>
<li>>= greater than or equal to</li>
<li>&lt;= lesser than or equal to</li>
<li>!= not equal to</li>
</ul>
<p>In the original scenario, we want to specify that the module can only be enabled on Drupal core 7.36 or later. To do this, we can use the "greater than or equal to" option.</p>
<pre><code class="language-ini">dependencies[] = system (&gt;=7.36)
</code></pre>
<p>Because we need to check for Drupal's core version, we're using the system module as the dependency and specifying that it needs to be either equal to or greater than 7.36. If this dependency is not met, e.g. Drupal 7.35 is being used, then the module cannot be enabled rather than showing a function not found error for <code>user_has_role()</code> when it is called.</p>
<p><img src="/assets/images/blog/minimum-drupal-version-d7.png" alt="A screenshot of the modules page showing System as a dependency for a custom module." /></p>
<h2 id="external-links">External Links</h2>
<ul>
<li><a href="https://www.drupal.org/node/542202#dependencies">Writing module .info files (Drupal 7.x)</a></li>
</ul>
<p class="tags">
Tags:
<a href="https://www.oliverdavies.uk/blog/tags/drupal">drupal</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupal-7">drupal-7</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupal-planet">drupal-planet</a> </p>
<div class="post-pager is-flex">
<div class="is-half">
<a href="/blog/2015/03/20/2014">
&laquo; 2014
</a>
</div>
<div class="is-half text-right">
<a href="/blog/2015/06/18/updating-forked-repositories-on-github">
Updating Forked Repositories on GitHub &raquo;
</a>
</div>
</div>
<div class="about-author">
<h2>About the Author</h2>
<img src="//images.oliverdavies.uk/assets/images/me-precedent.jpg" alt="Picture of Oliver" class="img-circle">
<p>Oliver Davies is a Web Developer, System Administrator and Drupal specialist based in the UK. He is a Senior Developer at <a href="https://microserve.io">Microserve</a> and also provides freelance consultancy services for Drupal websites, PHP applications and Linux servers.</p>
</div>
</main>
<div class="col-md-3">
<div class="panel badges text-center">
<a class="badge--da-member" href="https://assoc.drupal.org/membership" title="Im a Drupal Association member.">
<img
src="//images.oliverdavies.uk/assets/images/da-individual-member.png"
alt="Drupal Association Individual Member"
width="152"
>
</a>
<a href="http://drupalcores.com/#opdavies">
<img
alt="I built Drupal 8 with hand holding a wrench on blue background"
src="//images.oliverdavies.uk/assets/images/drupal-8.jpg"
/>
</a>
<img
src="//images.oliverdavies.uk/assets/images/badges/acquia-certified-developer-drupal-8.png"
alt="Acquia Certified Developer - Drupal 8 Exam Badge"
height="147" width="147"
/>
<a href="http://conference.phpnw.org.uk/phpnw17">
<img src="//images.oliverdavies.uk/assets/images/badges/phpnw17.png" alt="">
</a>
</div>
<div class="availability panel panel-default">
<div class="panel-heading">Availability</div>
<div class="panel-body">
<p>
<i class="fa fa-thumbs-o-up text-warning"></i>
Currently have limited part-time capacity
</p>
<p>
<i class="fa fa-thumbs-o-down text-danger"></i>
Currently no spare full-time capacity.
</p>
</div>
</div>
<div class="latest-posts panel panel-default">
<div class="latest-posts__heading panel-heading">Latest blog posts</div>
<ul class="list-group">
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot">
Introducing the Drupal Meetups Twitterbot
</a>
</span> -
<span class="post__date">9th June, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/20/turning-drupal-module-into-feature">
Turning Your Custom Drupal Module into a Feature
</a>
</span> -
<span class="post__date">20th May, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/15/drupalcamp-bristol-early-bird-tickets-sessions-sponsors">
DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
</a>
</span> -
<span class="post__date">15th May, 2017</span>
</li>
</ul>
</div>
</div>
</div> </div>
<footer class="container">
<p class="copyright">
&copy; 2010-2017 Oliver Davies. Built with <a href="https://sculpin.io">Sculpin</a>.
</p>
<div class="meetups">
<h2>Things that I organise</h2>
<ul>
<li class="meetups--drupal-bristol">
<a href="http://www.drupalbristol.org.uk" title="Drupal Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupal-bristol.jpeg" alt="Drupal Bristol">
</a>
</li>
<li class="meetups--drupalcamp-bristol">
<a href="http://www.drupalcampbristol.co.uk" title="DrupalCamp Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupalcamp-bristol.png" alt="DrupalCamp Bristol">
</a>
</li>
<li class="meetups--phpsw">
<a href="http://phpsw.uk" title="PHPSW">
<img src="//images.oliverdavies.uk/assets/images/meetups/phpsw.jpeg" alt="PHPSW">
</a>
</li>
</ul>
</div>
</footer>
<script src="https://www.oliverdavies.uk/assets/js/site.js"></script>
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11967257-1', 'auto'); ga('send', 'pageview');</script>
</body>
</html>

View file

@ -0,0 +1,298 @@
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<title>Updating Forked Repositories on GitHub | Oliver Davies</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="I just had to update a repo that I forked on GitHub. This is how I did it. Did I do it the correct way?">
<meta property="og:url" content="https://www.oliverdavies.uk/blog/2015/06/18/updating-forked-repositories-on-github">
<meta property="og:title" content="Updating Forked Repositories on GitHub"/>
<meta property="og:image" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg"/>
<meta property="og:image:height" content="327"/>
<meta property="og:image:type" content="image/jpg">
<meta property="og:image:width" content="327"/>
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/main.css">
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/blog-post.css">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=57" sizes="57x57">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=114" sizes="114x114">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=72" sizes="72x72">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=144" sizes="144x144">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=60" sizes="60x60">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=120" sizes="120x120">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=76" sizes="76x76">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=152" sizes="152x152">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=160" sizes="160x160">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=96" sizes="96x96">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=32" sizes="32x32">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=16" sizes="16x16">
</head>
<body class="">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://www.oliverdavies.uk/">Oliver Davies</a>
</div>
<div id="navbar" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li class="">
<a href="/">About</a>
</li>
<li class="">
<a href="/experience">Experience</a>
</li>
<li class="">
<a href="/testimonials">Testimonials</a>
</li>
<li class="">
<a href="/talks">Talks</a>
</li>
<li class="active">
<a href="/blog">Blog</a>
</li>
<li class="">
<a href="/contact">Contact</a>
</li>
</ul>
</div> </div>
</nav>
<div class="container">
<div class="row">
<main class="col-md-9">
<h1>Updating Forked Repositories on GitHub</h1>
<p class="posted">18th June 2015</p>
<h2 id="sculpin">Sculpin</h2>
<p>People may or may not know, but this site runs on <a href="https://sculpin.io/">Sculpin</a>, a PHP based static site generator (this may be the first time that I've mentioned it on this site). The source code is hosted on <a href="https://github.com/opdavies/oliverdavies.uk">GitHub</a>, and I've listed the site on the <a href="https://sculpin.io/community/">Community page</a> on the Sculpin website.</p>
<p>To get it there, I forked the <a href="https://github.com/sculpin/sculpin.io">main sculpin.io repository</a> so that I had <a href="https://github.com/opdavies/sculpin.io">my own copy</a>, created a branch, made my additions and submitted a pull request. Easy enough!</p>
<h2 id="new-domain">New Domain</h2>
<p>In the last week or so, I've changed this site URL from .co.uk to just .uk, and also updated the GitHub repo URL to match, so I wanted to update the Community page to use the correct URL.</p>
<p>There had been commits to the main repo since my pull request was merged, I didn't want to delete my repo and fork again, and making any changes against and old codebase isn't best practice, so I wanted to merge the latest changes into my forked repo before I did anything else - just to check that I didn't break anything!</p>
<h2 id="updating-my-local-repo">Updating my Local Repo</h2>
<p>I had a quick look for a <em>Update my fork</em> button or something, but couldn't see one to I added the main repository as an additional remote called <code>upstream</code> and fetched the changes.</p>
<pre><code class="language-bash">$ git remote add upstream https://github.com/sculpin/sculpin.io.git
$ git fetch upstream
remote: Counting objects: 33, done.
remote: Total 33 (delta 6), reused 6 (delta 6), pack-reused 27
Unpacking objects: 100% (33/33), done.
From https://github.com/sculpin/sculpin.io
* [new branch] master -&gt; upstream/master
* [new branch] pr/4 -&gt; upstream/pr/4
</code></pre>
<p>Now my local site knows about the upstream repo, and I could rebase the changes (<code>git pull upstream master</code> should have worked too) and push them back to origin.</p>
<pre><code class="language-bash">$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
...
Fast-forwarded master to upstream/master.
$ git push origin master
</code></pre>
<p>This seems to have worked OK - the commits are still authored by the correct people and at the correct date and time - and I went ahead and created a new feature branch and pull request based on that master branch.</p>
<figure>
<img src="/assets/images/blog/forked-github-repo-commits.png" alt="The commits on my master branch after rebasing">
<figcaption>The commits on my forked master branch after rebasing and pushing. All good!</figcaption>
</figure>
<figure>
<img src="/assets/images/blog/my-commit-to-the-rebased-branch.png" alt="The new feature branch with my additional commit.">
<figcaption>The new feature branch with the new commit.</figcaption>
</figure>
<h2 id="is-there-a-better-way%3F">Is There a Better Way?</h2>
<p>Did I miss something? Is there a recommended and/or better way to update your forked repos, maybe through the UI? Please <a href="https://twitter.com/?status=Rebasing GitHub Forks: @opdavies">send me a tweet</a> with any comments.</p>
<h2 id="update%3A-rebasing-in-phpstorm">Update: Rebasing in PhpStorm</h2>
<p><strong>December 2015:</strong> Ive found that PhpStorm has an option available to rebase a fork from within the IDE. This is within the <em>VCS</em> > <em>Git</em> menu.</p>
<p>I believe that it will use an existing "upstream" remote if it exists, otherwise it will add one automatically for you, linking to the repository that you forked from.</p>
<p>Once youve completed the rebase, you can then push your updated branch either from the terminal, or using the <em>Push</em> command from the same menu.</p>
<p><img src="/assets/images/blog/github-fork-rebase-phpstorm.png" alt="Rebasing a forked repository in PhpStorm using the VCS menu." /></p>
<p>It would be great to see something similar added to <a href="https://hub.github.com">hub</a> too (Ive created <a href="https://github.com/github/hub/issues/1047">an issue</a>)!</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="http://blog.jetbrains.com/idea/2011/02/advanced-github-integration-rebase-my-github-fork/">PhpStorm - Advanced GitHub Integration: Rebase My GitHub Fork (blog post)</a></li>
<li><a href="https://www.youtube.com/watch?v=Twy-dhVgN4k">Rebasing a GitHub fork inside PhpStorm (video)</a></li>
<li><a href="https://hub.github.com">hub</a> - makes Git better with GitHub</li>
</ul>
<p class="tags">
Tags:
<a href="https://www.oliverdavies.uk/blog/tags/git">git</a>, <a href="https://www.oliverdavies.uk/blog/tags/github">github</a>, <a href="https://www.oliverdavies.uk/blog/tags/phpstorm">phpstorm</a>, <a href="https://www.oliverdavies.uk/blog/tags/sculpin">sculpin</a> </p>
<div class="post-pager is-flex">
<div class="is-half">
<a href="/blog/2015/04/03/how-to-define-a-minimum-drupal-core-version">
&laquo; How to Define a Minimum Drupal Core Version
</a>
</div>
<div class="is-half text-right">
<a href="/blog/2015/07/19/sculpin-twig-resources">
Sculpin and Twig Resources &raquo;
</a>
</div>
</div>
<div class="about-author">
<h2>About the Author</h2>
<img src="//images.oliverdavies.uk/assets/images/me-precedent.jpg" alt="Picture of Oliver" class="img-circle">
<p>Oliver Davies is a Web Developer, System Administrator and Drupal specialist based in the UK. He is a Senior Developer at <a href="https://microserve.io">Microserve</a> and also provides freelance consultancy services for Drupal websites, PHP applications and Linux servers.</p>
</div>
</main>
<div class="col-md-3">
<div class="panel badges text-center">
<a class="badge--da-member" href="https://assoc.drupal.org/membership" title="Im a Drupal Association member.">
<img
src="//images.oliverdavies.uk/assets/images/da-individual-member.png"
alt="Drupal Association Individual Member"
width="152"
>
</a>
<a href="http://drupalcores.com/#opdavies">
<img
alt="I built Drupal 8 with hand holding a wrench on blue background"
src="//images.oliverdavies.uk/assets/images/drupal-8.jpg"
/>
</a>
<img
src="//images.oliverdavies.uk/assets/images/badges/acquia-certified-developer-drupal-8.png"
alt="Acquia Certified Developer - Drupal 8 Exam Badge"
height="147" width="147"
/>
<a href="http://conference.phpnw.org.uk/phpnw17">
<img src="//images.oliverdavies.uk/assets/images/badges/phpnw17.png" alt="">
</a>
</div>
<div class="availability panel panel-default">
<div class="panel-heading">Availability</div>
<div class="panel-body">
<p>
<i class="fa fa-thumbs-o-up text-warning"></i>
Currently have limited part-time capacity
</p>
<p>
<i class="fa fa-thumbs-o-down text-danger"></i>
Currently no spare full-time capacity.
</p>
</div>
</div>
<div class="latest-posts panel panel-default">
<div class="latest-posts__heading panel-heading">Latest blog posts</div>
<ul class="list-group">
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot">
Introducing the Drupal Meetups Twitterbot
</a>
</span> -
<span class="post__date">9th June, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/20/turning-drupal-module-into-feature">
Turning Your Custom Drupal Module into a Feature
</a>
</span> -
<span class="post__date">20th May, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/15/drupalcamp-bristol-early-bird-tickets-sessions-sponsors">
DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
</a>
</span> -
<span class="post__date">15th May, 2017</span>
</li>
</ul>
</div>
</div>
</div> </div>
<footer class="container">
<p class="copyright">
&copy; 2010-2017 Oliver Davies. Built with <a href="https://sculpin.io">Sculpin</a>.
</p>
<div class="meetups">
<h2>Things that I organise</h2>
<ul>
<li class="meetups--drupal-bristol">
<a href="http://www.drupalbristol.org.uk" title="Drupal Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupal-bristol.jpeg" alt="Drupal Bristol">
</a>
</li>
<li class="meetups--drupalcamp-bristol">
<a href="http://www.drupalcampbristol.co.uk" title="DrupalCamp Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupalcamp-bristol.png" alt="DrupalCamp Bristol">
</a>
</li>
<li class="meetups--phpsw">
<a href="http://phpsw.uk" title="PHPSW">
<img src="//images.oliverdavies.uk/assets/images/meetups/phpsw.jpeg" alt="PHPSW">
</a>
</li>
</ul>
</div>
</footer>
<script src="https://www.oliverdavies.uk/assets/js/site.js"></script>
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11967257-1', 'auto'); ga('send', 'pageview');</script>
</body>
</html>

View file

@ -0,0 +1,271 @@
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<title>Sculpin and Twig Resources | Oliver Davies</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="A compiled list of resources relating to Sculpin and Twig.">
<meta property="og:url" content="https://www.oliverdavies.uk/blog/2015/07/19/sculpin-twig-resources">
<meta property="og:title" content="Sculpin and Twig Resources"/>
<meta property="og:image" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg"/>
<meta property="og:image:height" content="327"/>
<meta property="og:image:type" content="image/jpg">
<meta property="og:image:width" content="327"/>
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/main.css">
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/blog-post.css">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=57" sizes="57x57">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=114" sizes="114x114">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=72" sizes="72x72">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=144" sizes="144x144">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=60" sizes="60x60">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=120" sizes="120x120">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=76" sizes="76x76">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=152" sizes="152x152">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=160" sizes="160x160">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=96" sizes="96x96">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=32" sizes="32x32">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=16" sizes="16x16">
</head>
<body class="">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://www.oliverdavies.uk/">Oliver Davies</a>
</div>
<div id="navbar" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li class="">
<a href="/">About</a>
</li>
<li class="">
<a href="/experience">Experience</a>
</li>
<li class="">
<a href="/testimonials">Testimonials</a>
</li>
<li class="">
<a href="/talks">Talks</a>
</li>
<li class="active">
<a href="/blog">Blog</a>
</li>
<li class="">
<a href="/contact">Contact</a>
</li>
</ul>
</div> </div>
</nav>
<div class="container">
<div class="row">
<main class="col-md-9">
<h1>Sculpin and Twig Resources</h1>
<p class="posted">19th July 2015</p>
<p>Heres a list of resources that I compiled whilst preparing for my <a href="http://drupalcampnorth.org/session/test-drive-twig-sculpin">Sculpin and Twig talk</a> at <a href="http://drupalcampnorth.org">DrupalCamp North</a>.</p>
<h2 id="general-information">General Information</h2>
<ul>
<li><a href="https://sculpin.io">https://sculpin.io</a></li>
<li><a href="https://sculpin.io/getstarted/">https://sculpin.io/getstarted/</a></li>
</ul>
<h2 id="where-to-get-sculpin">Where to Get Sculpin</h2>
<ul>
<li><a href="https://sculpin.io/download/">https://sculpin.io/download/</a></li>
<li><a href="https://github.com/sculpin/sculpin">https://github.com/sculpin/sculpin</a></li>
<li><a href="https://github.com/sculpin/sculpin-blog-skeleton">https://github.com/sculpin/sculpin-blog-skeleton</a></li>
<li><a href="https://github.com/opdavies/sculpin-minimal">https://github.com/opdavies/sculpin-minimal</a></li>
</ul>
<h2 id="source-code-examples">Source Code Examples</h2>
<ul>
<li><a href="https://sculpin.io/community/">https://sculpin.io/community/</a></li>
<li><a href="https://github.com/opdavies/oliverdavies.uk">https://github.com/opdavies/oliverdavies.uk</a> - the source repository for this site.</li>
<li><a href="https://github.com/simensen/beau.io">https://github.com/simensen/beau.io</a></li>
<li><a href="https://github.com/simensen/srcmvn.com">https://github.com/simensen/srcmvn.com</a></li>
<li><a href="https://github.com/thatpodcast/thatpodcast.io">https://github.com/thatpodcast/thatpodcast.io</a></li>
<li><a href="https://github.com/MidwestPHP/mwphp15">https://github.com/MidwestPHP/mwphp15</a></li>
<li><a href="https://github.com/dev-human/dev-human">https://github.com/dev-human/dev-human</a></li>
<li><a href="https://github.com/pantheon-systems/documentation">https://github.com/pantheon-systems/documentation</a></li>
<li>Google for "<code>sculpin_site.yml site:github.com</code>" for more examples.</li>
</ul>
<h2 id="videos">Videos</h2>
<ul>
<li><a href="http://bit.ly/sculpin-videos">http://bit.ly/sculpin-videos</a> - a YouTube playlist of Sculpin videos.</li>
</ul>
<h2 id="twig">Twig</h2>
<ul>
<li><a href="http://twig.sensiolabs.org/">http://twig.sensiolabs.org/</a></li>
<li><a href="http://twig.sensiolabs.org/doc/templates.html">http://twig.sensiolabs.org/doc/templates.html</a> - variables, filters, functions, template inheritance, expressions etc.</li>
<li>Go to http://twig.sensiolabs.org/{foo} to search for a tag, filter, test or function.</li>
</ul>
<p class="tags">
Tags:
<a href="https://www.oliverdavies.uk/blog/tags/sculpin">sculpin</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupalcamp">drupalcamp</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupalcamp-north">drupalcamp-north</a>, <a href="https://www.oliverdavies.uk/blog/tags/twig">twig</a> </p>
<div class="post-pager is-flex">
<div class="is-half">
<a href="/blog/2015/06/18/updating-forked-repositories-on-github">
&laquo; Updating Forked Repositories on GitHub
</a>
</div>
<div class="is-half text-right">
<a href="/blog/2015/07/21/automating-sculpin-jenkins">
Automating Sculpin Builds with Jenkins CI &raquo;
</a>
</div>
</div>
<div class="about-author">
<h2>About the Author</h2>
<img src="//images.oliverdavies.uk/assets/images/me-precedent.jpg" alt="Picture of Oliver" class="img-circle">
<p>Oliver Davies is a Web Developer, System Administrator and Drupal specialist based in the UK. He is a Senior Developer at <a href="https://microserve.io">Microserve</a> and also provides freelance consultancy services for Drupal websites, PHP applications and Linux servers.</p>
</div>
</main>
<div class="col-md-3">
<div class="panel badges text-center">
<a class="badge--da-member" href="https://assoc.drupal.org/membership" title="Im a Drupal Association member.">
<img
src="//images.oliverdavies.uk/assets/images/da-individual-member.png"
alt="Drupal Association Individual Member"
width="152"
>
</a>
<a href="http://drupalcores.com/#opdavies">
<img
alt="I built Drupal 8 with hand holding a wrench on blue background"
src="//images.oliverdavies.uk/assets/images/drupal-8.jpg"
/>
</a>
<img
src="//images.oliverdavies.uk/assets/images/badges/acquia-certified-developer-drupal-8.png"
alt="Acquia Certified Developer - Drupal 8 Exam Badge"
height="147" width="147"
/>
<a href="http://conference.phpnw.org.uk/phpnw17">
<img src="//images.oliverdavies.uk/assets/images/badges/phpnw17.png" alt="">
</a>
</div>
<div class="availability panel panel-default">
<div class="panel-heading">Availability</div>
<div class="panel-body">
<p>
<i class="fa fa-thumbs-o-up text-warning"></i>
Currently have limited part-time capacity
</p>
<p>
<i class="fa fa-thumbs-o-down text-danger"></i>
Currently no spare full-time capacity.
</p>
</div>
</div>
<div class="latest-posts panel panel-default">
<div class="latest-posts__heading panel-heading">Latest blog posts</div>
<ul class="list-group">
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot">
Introducing the Drupal Meetups Twitterbot
</a>
</span> -
<span class="post__date">9th June, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/20/turning-drupal-module-into-feature">
Turning Your Custom Drupal Module into a Feature
</a>
</span> -
<span class="post__date">20th May, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/15/drupalcamp-bristol-early-bird-tickets-sessions-sponsors">
DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
</a>
</span> -
<span class="post__date">15th May, 2017</span>
</li>
</ul>
</div>
</div>
</div> </div>
<footer class="container">
<p class="copyright">
&copy; 2010-2017 Oliver Davies. Built with <a href="https://sculpin.io">Sculpin</a>.
</p>
<div class="meetups">
<h2>Things that I organise</h2>
<ul>
<li class="meetups--drupal-bristol">
<a href="http://www.drupalbristol.org.uk" title="Drupal Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupal-bristol.jpeg" alt="Drupal Bristol">
</a>
</li>
<li class="meetups--drupalcamp-bristol">
<a href="http://www.drupalcampbristol.co.uk" title="DrupalCamp Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupalcamp-bristol.png" alt="DrupalCamp Bristol">
</a>
</li>
<li class="meetups--phpsw">
<a href="http://phpsw.uk" title="PHPSW">
<img src="//images.oliverdavies.uk/assets/images/meetups/phpsw.jpeg" alt="PHPSW">
</a>
</li>
</ul>
</div>
</footer>
<script src="https://www.oliverdavies.uk/assets/js/site.js"></script>
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11967257-1', 'auto'); ga('send', 'pageview');</script>
</body>
</html>

View file

@ -0,0 +1,340 @@
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<title>Automating Sculpin Builds with Jenkins CI | Oliver Davies</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:url" content="https://www.oliverdavies.uk/blog/2015/07/21/automating-sculpin-jenkins">
<meta property="og:title" content="Automating Sculpin Builds with Jenkins CI"/>
<meta property="og:image" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg"/>
<meta property="og:image:height" content="327"/>
<meta property="og:image:type" content="image/jpg">
<meta property="og:image:width" content="327"/>
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/main.css">
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/blog-post.css">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=57" sizes="57x57">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=114" sizes="114x114">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=72" sizes="72x72">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=144" sizes="144x144">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=60" sizes="60x60">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=120" sizes="120x120">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=76" sizes="76x76">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=152" sizes="152x152">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=160" sizes="160x160">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=96" sizes="96x96">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=32" sizes="32x32">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=16" sizes="16x16">
</head>
<body class="">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://www.oliverdavies.uk/">Oliver Davies</a>
</div>
<div id="navbar" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li class="">
<a href="/">About</a>
</li>
<li class="">
<a href="/experience">Experience</a>
</li>
<li class="">
<a href="/testimonials">Testimonials</a>
</li>
<li class="">
<a href="/talks">Talks</a>
</li>
<li class="active">
<a href="/blog">Blog</a>
</li>
<li class="">
<a href="/contact">Contact</a>
</li>
</ul>
</div> </div>
</nav>
<div class="container">
<div class="row">
<main class="col-md-9">
<h1>Automating Sculpin Builds with Jenkins CI</h1>
<p class="posted">21st July 2015</p>
<p>As part of re-building this site with <a href="http://sculpin.io">Sculpin</a>, I wanted to automate the deployments, as in I wouldn't need to run a script like <a href="https://raw.githubusercontent.com/sculpin/sculpin-blog-skeleton/master/publish.sh">publish.sh</a> locally and have that deploy my code onto my server. Not only did that mean that my local workflow was simpler (update, commit and push, rather than update, commit, push and deploy), but if I wanted to make a quick edit or hotfix, I could log into GitHub or Bitbucket (wherever I decided to host the source code) from any computer or my phone, make the change and have it deployed for me.</p>
<p>I'd started using <a href="http://jenkins-ci.org">Jenkins CI</a> during my time at the Drupal Association, and had since built my own Jenkins server to handle deployments of Drupal websites, so that was the logical choice to use.</p>
<h2 id="installing-jenkins-and-sculpin">Installing Jenkins and Sculpin</h2>
<p>If you dont already have Jenkins installed and configured, I'd suggest using <a href="http://jeffgeerling.com/">Jeff Geerling</a> (aka geerlingguy)'s <a href="https://galaxy.ansible.com/list#/roles/440">Ansible role for Jenkins CI</a>.</p>
<p>I've also released an <a href="https://galaxy.ansible.com/list#/roles/4063">Ansible role for Sculpin</a> that installs the executable so that the Jenkins server can run Sculpin commands.</p>
<h2 id="triggering-a-build-from-a-git-commit">Triggering a Build from a Git Commit</h2>
<p>I created a new Jenkins item for this task, and restricted where it could be run to <code>master</code> (i.e. the Jenkins server rather than any of the nodes).</p>
<h3 id="polling-from-git">Polling from Git</h3>
<p>I entered the url to the <a href="https://github.com/opdavies/oliverdavies.uk">GitHub repo</a> into the <strong>Source Code Management</strong> section (the Git option <em>may</em> have been added by the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin">Git plugin</a> that I have installed).</p>
<p>As we dont need any write access back to the repo, using the HTTP URL rather than the SSH one was fine, and I didnt need to provide any additional credentials.</p>
<p>Also, as I knew that Id be working a lot with feature branches, I entered <code>*/master</code> as the only branch to build. This meant that pushing changes or making edits on any other branches would not trigger a build.</p>
<p><img src="/assets/images/blog/oliverdavies-uk-jenkins-git-repo.png" alt="Defining the Git repository in Jenkins" /></p>
<p>I also checked the <strong>Poll SCM</strong> option so that Jenkins would be routinely checking for updated code. This essentially uses the same syntax as cron, specifying minutes, hours etc. I entered <code>* * * * *</code> so that Jenkins would poll each minute, knowing that I could make this less frequent if needed.</p>
<p>This now that Jenkins would be checking for any updates to the repo each minute, and could execute tasks if needed.</p>
<h3 id="building-and-deploying">Building and Deploying</h3>
<p>Within the <strong>Builds</strong> section of the item, I added an <em>Execute Shell</em> step, where I could enter a command to execute. Here, I pasted a modified version of the original publish.sh script.</p>
<pre><code class="language-bash">#!/bin/bash
set -uex
sculpin generate --env=prod --quiet
if [ $? -ne 0 ]; then echo "Could not generate the site"; exit 1; fi
rsync -avze 'ssh' --delete output_prod/ prodwww2:/var/www/html/oliverdavies.uk/htdocs
if [ $? -ne 0 ]; then echo "Could not publish the site"; exit 1; fi
</code></pre>
<p>This essentially is the same as the original file, in that Sculpin generates the site, and uses rsync to deploy it somewhere else. In my case, <code>prodwww2</code> is a Jenkins node (this alias is configured in <code>/var/lib/jenkins/.ssh/config</code>), and <code>/var/www/html/oliverdavies.uk/htdocs</code> is the directory from where my site is served.</p>
<h2 id="building-periodically">Building Periodically</h2>
<p>There is some dynamic content on my site, specifically on the Talks page. Each talk has a date assigned to it, and within the Twig template, the talk is positoned within upcoming or previous talks based on whether this date is less or greater than the time of the build.</p>
<p>The YAML front matter:</p>
<pre><code class="language-yaml">---
...
talks:
- title: Test Drive Twig with Sculpin
date: 2015-07-24
location: DrupalCamp North
---
</code></pre>
<p>The Twig layout:</p>
<pre><code class="language-twig">{% for talk in talks|reverse if talk.date &gt;= now %}
{# Upcoming talks #}
{% endfor %}
{% for talk in talks if talk.date &lt; now %}
{# Previous talks #}
{% endfor%}
</code></pre>
<p>I also didnt want to have to push an empty commit or manually trigger a job in Jenkins after doing a talk in order for it to be positioned in the correct place on the page, so I also wanted Jenkins to schedule a regular build regardless of whether or not code had been pushed, so ensure that my talks page would be up to date.</p>
<p>After originally thinking that I'd have to split the build steps into a separate item and trigger that from a scheduled item, and amend my git commit item accordingly, I found a <strong>Build periodically</strong> option that I could use within the same item, leaving it intact and not having to make amends.</p>
<p>I set this to <code>@daily</code> (the same <code>H H * * *</code> - <code>H</code> is a Jenkins thing), so that the build would be triggered automatically each day without a commit, and deploy any updates to the site.</p>
<p><img src="/assets/images/blog/oliverdavies-uk-jenkins-git-timer.png" alt="Setting Jenkins to periodically build a new version of the site." /></p>
<h2 id="next-steps">Next Steps</h2>
<p>This workflow works great for one site, but as I roll out more Sculpin sites, I'd like to reduce duplication. I see this mainly as Ill end up creating a separate <code>sculpin_build</code> item thats decoupled from the site that its building, and instead passing variables such as environment, server name and docroot path as parameters in a parameterized build.</p>
<p>I'll probably also take the raw shell script out of Jenkins and save it in a text file that's stored locally on the server, and execute that via Jenkins. This means that Id be able to store this file in a separate Git repository with my other Jenkins scripts and get the standard advantages of using version control.</p>
<h2 id="update">Update</h2>
<p>Since publishing this post, I've added some more items to the original build script.</p>
<h3 id="updating-composer">Updating Composer</h3>
<pre><code class="language-bash">if [ -f composer.json ]; then
/usr/local/bin/composer install
fi
</code></pre>
<p>Updates project dependencies via <a href="https://getcomposer.org/doc/00-intro.md#introduction">Composer</a> if composer.json exists.</p>
<h3 id="updating-sculpin-dependencies">Updating Sculpin Dependencies</h3>
<pre><code class="language-bash">if [ -f sculpin.json ]; then
sculpin install
fi
</code></pre>
<p>Runs <code>sculpin install</code> on each build if the sculpin.json file exists, to ensure that the required custom bundles and dependencies are installed.</p>
<h3 id="managing-redirects">Managing Redirects</h3>
<pre><code class="language-bash">if [ -f scripts/redirects.php ]; then
/usr/bin/php scripts/redirects.php
fi
</code></pre>
<p>I've been working on a <code>redirects.php</code> script that generates redirects from a .csv file, after seeing similar things in the <a href="https://github.com/pantheon-systems/documentation">Pantheon Documentation</a> and <a href="https://github.com/thatpodcast/thatpodcast.io">That Podcast</a> repositories. This checks if that file exists, and if so, runs it and generates the source file containing each redirect.</p>
<p class="tags">
Tags:
<a href="https://www.oliverdavies.uk/blog/tags/sculpin">sculpin</a>, <a href="https://www.oliverdavies.uk/blog/tags/jenkins">jenkins</a> </p>
<div class="post-pager is-flex">
<div class="is-half">
<a href="/blog/2015/07/19/sculpin-twig-resources">
&laquo; Sculpin and Twig Resources
</a>
</div>
<div class="is-half text-right">
<a href="/blog/2015/12/22/programmatically-load-an-entityform-in-drupal-7">
Programmatically Load an Entityform in Drupal 7 &raquo;
</a>
</div>
</div>
<div class="about-author">
<h2>About the Author</h2>
<img src="//images.oliverdavies.uk/assets/images/me-precedent.jpg" alt="Picture of Oliver" class="img-circle">
<p>Oliver Davies is a Web Developer, System Administrator and Drupal specialist based in the UK. He is a Senior Developer at <a href="https://microserve.io">Microserve</a> and also provides freelance consultancy services for Drupal websites, PHP applications and Linux servers.</p>
</div>
</main>
<div class="col-md-3">
<div class="panel badges text-center">
<a class="badge--da-member" href="https://assoc.drupal.org/membership" title="Im a Drupal Association member.">
<img
src="//images.oliverdavies.uk/assets/images/da-individual-member.png"
alt="Drupal Association Individual Member"
width="152"
>
</a>
<a href="http://drupalcores.com/#opdavies">
<img
alt="I built Drupal 8 with hand holding a wrench on blue background"
src="//images.oliverdavies.uk/assets/images/drupal-8.jpg"
/>
</a>
<img
src="//images.oliverdavies.uk/assets/images/badges/acquia-certified-developer-drupal-8.png"
alt="Acquia Certified Developer - Drupal 8 Exam Badge"
height="147" width="147"
/>
<a href="http://conference.phpnw.org.uk/phpnw17">
<img src="//images.oliverdavies.uk/assets/images/badges/phpnw17.png" alt="">
</a>
</div>
<div class="availability panel panel-default">
<div class="panel-heading">Availability</div>
<div class="panel-body">
<p>
<i class="fa fa-thumbs-o-up text-warning"></i>
Currently have limited part-time capacity
</p>
<p>
<i class="fa fa-thumbs-o-down text-danger"></i>
Currently no spare full-time capacity.
</p>
</div>
</div>
<div class="latest-posts panel panel-default">
<div class="latest-posts__heading panel-heading">Latest blog posts</div>
<ul class="list-group">
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot">
Introducing the Drupal Meetups Twitterbot
</a>
</span> -
<span class="post__date">9th June, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/20/turning-drupal-module-into-feature">
Turning Your Custom Drupal Module into a Feature
</a>
</span> -
<span class="post__date">20th May, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/15/drupalcamp-bristol-early-bird-tickets-sessions-sponsors">
DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
</a>
</span> -
<span class="post__date">15th May, 2017</span>
</li>
</ul>
</div>
</div>
</div> </div>
<footer class="container">
<p class="copyright">
&copy; 2010-2017 Oliver Davies. Built with <a href="https://sculpin.io">Sculpin</a>.
</p>
<div class="meetups">
<h2>Things that I organise</h2>
<ul>
<li class="meetups--drupal-bristol">
<a href="http://www.drupalbristol.org.uk" title="Drupal Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupal-bristol.jpeg" alt="Drupal Bristol">
</a>
</li>
<li class="meetups--drupalcamp-bristol">
<a href="http://www.drupalcampbristol.co.uk" title="DrupalCamp Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupalcamp-bristol.png" alt="DrupalCamp Bristol">
</a>
</li>
<li class="meetups--phpsw">
<a href="http://phpsw.uk" title="PHPSW">
<img src="//images.oliverdavies.uk/assets/images/meetups/phpsw.jpeg" alt="PHPSW">
</a>
</li>
</ul>
</div>
</footer>
<script src="https://www.oliverdavies.uk/assets/js/site.js"></script>
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11967257-1', 'auto'); ga('send', 'pageview');</script>
</body>
</html>

View file

@ -0,0 +1,262 @@
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<title>Programmatically Load an Entityform in Drupal 7 | Oliver Davies</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="How to programmatically load, render and embed an entityform in Drupal 7.">
<meta property="og:url" content="https://www.oliverdavies.uk/blog/2015/12/22/programmatically-load-an-entityform-in-drupal-7">
<meta property="og:title" content="Programmatically Load an Entityform in Drupal 7"/>
<meta property="og:image" content="https://www.oliverdavies.uk/assets/images/me-precedent.jpg"/>
<meta property="og:image:height" content="327"/>
<meta property="og:image:type" content="image/jpg">
<meta property="og:image:width" content="327"/>
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/main.css">
<link rel="stylesheet" href="https://www.oliverdavies.uk/assets/css/blog-post.css">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=57" sizes="57x57">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=114" sizes="114x114">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=72" sizes="72x72">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=144" sizes="144x144">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=60" sizes="60x60">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=120" sizes="120x120">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=76" sizes="76x76">
<link rel="apple-touch-icon" href="/assets/images/me-precedent.jpg?s=152" sizes="152x152">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=160" sizes="160x160">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=96" sizes="96x96">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=32" sizes="32x32">
<link rel="icon" href="/assets/images/me-precedent.jpg?s=16" sizes="16x16">
</head>
<body class="">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://www.oliverdavies.uk/">Oliver Davies</a>
</div>
<div id="navbar" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li class="">
<a href="/">About</a>
</li>
<li class="">
<a href="/experience">Experience</a>
</li>
<li class="">
<a href="/testimonials">Testimonials</a>
</li>
<li class="">
<a href="/talks">Talks</a>
</li>
<li class="active">
<a href="/blog">Blog</a>
</li>
<li class="">
<a href="/contact">Contact</a>
</li>
</ul>
</div> </div>
</nav>
<div class="container">
<div class="row">
<main class="col-md-9">
<h1>Programmatically Load an Entityform in Drupal 7</h1>
<p class="posted">22nd December 2015</p>
<p>I recently had my first experience using the <a href="https://www.drupal.org/project/entityform">Entityform module</a> in a project. It was quite easy to configure with different form types, but then I needed to embed the form into an overlay. I was expecting to use the <code>drupal_get_form()</code> function and render it, but this didnt work.</p>
<p>Here are the steps that I took to be able to load, render and embed the form.</p>
<h2 id="loading-the-form">Loading the Form</h2>
<p>The first thing that I needed to do to render the form was to load an empty instance of the entityform using <code>entityform_empty_load()</code>. In this example, <code>newsletter</code> is the name of my form type.</p>
<pre><code class="language-php">$form = entityform_empty_load('newsletter');
</code></pre>
<p>This returns an instance of a relevant <code>Entityform</code> object.</p>
<h2 id="rendering-the-form">Rendering the Form</h2>
<p>The next step was to be able to render the form. I did this using the <code>entity_form_wrapper()</code> function.</p>
<p>As this function is within the <code>entityform.admin.inc</code> file and not autoloaded by Drupal, I needed to include it using <code>module_load_include()</code> so that the function was available.</p>
<pre><code class="language-php">module_load_include('inc', 'entityform', 'entityform.admin');
$output = entityform_form_wrapper($form, 'submit', 'embedded'),
</code></pre>
<p>The first argument is the <code>Entityform</code> object that was created in the previous step (Ive <a href="https://www.drupal.org/node/2639584">submitted a patch</a> to type hint this within entityform so that its clearer what is expected), which is required.</p>
<p>The other two arguments are optional. The second argument is the mode (<code>submit</code> is the default value), and the last is the form context. <code>page</code> is the default value, for use on the submit page, however I changed this to <code>embedded</code>.</p>
<p>I could then pass this result into my theme function to render it successfully within the relevant template file.</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://www.drupal.org/project/entityform">The entityform module</a></li>
<li><a href="https://www.drupal.org/node/2639584">My issue and patch to add the type hint to the entityform_form_wrapper function</a></li>
</ul>
<p class="tags">
Tags:
<a href="https://www.oliverdavies.uk/blog/tags/drupal">drupal</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupal-7">drupal-7</a>, <a href="https://www.oliverdavies.uk/blog/tags/drupal-planet">drupal-planet</a>, <a href="https://www.oliverdavies.uk/blog/tags/entityform">entityform</a> </p>
<div class="post-pager is-flex">
<div class="is-half">
<a href="/blog/2015/07/21/automating-sculpin-jenkins">
&laquo; Automating Sculpin Builds with Jenkins CI
</a>
</div>
<div class="is-half text-right">
<a href="/blog/2016/02/15/announcing-the-drupal-vm-generator">
Announcing the Drupal VM Generator &raquo;
</a>
</div>
</div>
<div class="about-author">
<h2>About the Author</h2>
<img src="//images.oliverdavies.uk/assets/images/me-precedent.jpg" alt="Picture of Oliver" class="img-circle">
<p>Oliver Davies is a Web Developer, System Administrator and Drupal specialist based in the UK. He is a Senior Developer at <a href="https://microserve.io">Microserve</a> and also provides freelance consultancy services for Drupal websites, PHP applications and Linux servers.</p>
</div>
</main>
<div class="col-md-3">
<div class="panel badges text-center">
<a class="badge--da-member" href="https://assoc.drupal.org/membership" title="Im a Drupal Association member.">
<img
src="//images.oliverdavies.uk/assets/images/da-individual-member.png"
alt="Drupal Association Individual Member"
width="152"
>
</a>
<a href="http://drupalcores.com/#opdavies">
<img
alt="I built Drupal 8 with hand holding a wrench on blue background"
src="//images.oliverdavies.uk/assets/images/drupal-8.jpg"
/>
</a>
<img
src="//images.oliverdavies.uk/assets/images/badges/acquia-certified-developer-drupal-8.png"
alt="Acquia Certified Developer - Drupal 8 Exam Badge"
height="147" width="147"
/>
<a href="http://conference.phpnw.org.uk/phpnw17">
<img src="//images.oliverdavies.uk/assets/images/badges/phpnw17.png" alt="">
</a>
</div>
<div class="availability panel panel-default">
<div class="panel-heading">Availability</div>
<div class="panel-body">
<p>
<i class="fa fa-thumbs-o-up text-warning"></i>
Currently have limited part-time capacity
</p>
<p>
<i class="fa fa-thumbs-o-down text-danger"></i>
Currently no spare full-time capacity.
</p>
</div>
</div>
<div class="latest-posts panel panel-default">
<div class="latest-posts__heading panel-heading">Latest blog posts</div>
<ul class="list-group">
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot">
Introducing the Drupal Meetups Twitterbot
</a>
</span> -
<span class="post__date">9th June, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/20/turning-drupal-module-into-feature">
Turning Your Custom Drupal Module into a Feature
</a>
</span> -
<span class="post__date">20th May, 2017</span>
</li>
<li class="post list-group-item">
<span class="post__title">
<a href="/blog/2017/05/15/drupalcamp-bristol-early-bird-tickets-sessions-sponsors">
DrupalCamp Bristol 2017 - Early Bird Tickets, Call for Sessions, Sponsors
</a>
</span> -
<span class="post__date">15th May, 2017</span>
</li>
</ul>
</div>
</div>
</div> </div>
<footer class="container">
<p class="copyright">
&copy; 2010-2017 Oliver Davies. Built with <a href="https://sculpin.io">Sculpin</a>.
</p>
<div class="meetups">
<h2>Things that I organise</h2>
<ul>
<li class="meetups--drupal-bristol">
<a href="http://www.drupalbristol.org.uk" title="Drupal Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupal-bristol.jpeg" alt="Drupal Bristol">
</a>
</li>
<li class="meetups--drupalcamp-bristol">
<a href="http://www.drupalcampbristol.co.uk" title="DrupalCamp Bristol">
<img src="//images.oliverdavies.uk/assets/images/meetups/drupalcamp-bristol.png" alt="DrupalCamp Bristol">
</a>
</li>
<li class="meetups--phpsw">
<a href="http://phpsw.uk" title="PHPSW">
<img src="//images.oliverdavies.uk/assets/images/meetups/phpsw.jpeg" alt="PHPSW">
</a>
</li>
</ul>
</div>
</footer>
<script src="https://www.oliverdavies.uk/assets/js/site.js"></script>
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11967257-1', 'auto'); ga('send', 'pageview');</script>
</body>
</html>