mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
508 lines
22 KiB
HTML
508 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Preparing Your Application</title>
|
|
<link href='http://fonts.googleapis.com/css?family=Enriqueta' rel='stylesheet' type='text/css'>
|
|
<script type="text/javascript" src="//use.typekit.net/itm5ubu.js"></script>
|
|
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
|
<link rel="stylesheet" href="/css/foundation.css" />
|
|
<link rel="stylesheet" href="/css/capistrano.css">
|
|
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
|
<link rel="stylesheet" href="/css/okaidia.css">
|
|
<script src="/js/vendor/custom.modernizr.js"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<script type="text/javascript">
|
|
var _gauges = _gauges || [];
|
|
(function() {
|
|
var t = document.createElement('script');
|
|
t.type = 'text/javascript';
|
|
t.async = true;
|
|
t.id = 'gauges-tracker';
|
|
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
|
t.src = '//secure.gaug.es/track.js';
|
|
var s = document.getElementsByTagName('script')[0];
|
|
s.parentNode.insertBefore(t, s);
|
|
})();
|
|
</script>
|
|
|
|
<script type="text/javascript">
|
|
setTimeout(function(){var a=document.createElement("script");
|
|
var b=document.getElementsByTagName("script")[0];
|
|
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
|
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
|
</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-41970098-1', 'capistranorb.com');
|
|
ga('send', 'pageview');
|
|
</script>
|
|
<div class="top-bar">
|
|
<a href="/" class="brand">
|
|
<img src="/images/CapistranoLogo.png" />
|
|
</a>
|
|
</div>
|
|
|
|
|
|
<div class="row">
|
|
<div class="large-4 columns">
|
|
<ul class="side-nav">
|
|
<li><a href="http://www.harrow.io/" class="advertisment"><span class="label label-important">New</span> Hosted Capistrano for Teams</a></li>
|
|
<li class="divider"></li>
|
|
<h5>Overview</h5>
|
|
<li><a href="/documentation/overview/what-is-capistrano/">What is Capistrano?</a></li>
|
|
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
|
<li class="divider"></li>
|
|
<h5>Getting Started</h5>
|
|
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
|
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
|
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
|
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
|
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
|
<li class="divider"></li>
|
|
<h5>Troubleshooting</h5>
|
|
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
|
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
|
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
|
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
|
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
|
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
|
<li class="divider"></li>
|
|
<h5>FAQ</h5>
|
|
<li><a
|
|
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
|
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
|
<li class="divider"></li>
|
|
<h5>Power Use-Cases</h5>
|
|
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
|
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
|
<li class="divider"></li>
|
|
<h5>Recent Announcements</h5>
|
|
|
|
<li><a href="/2013/06/01/release-announcement.html"><span class="post-date">01 Jun 2013</span> Capistrano Version 3 Release Announcement</a></li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
<div class="large-8 column">
|
|
<div class="content">
|
|
<h2>Preparing Your Application</h2>
|
|
<div class="alert-box radius">
|
|
This will focus on preparing a Rails application, but most ideas expressed
|
|
here have parallels in Python, or PHP applications
|
|
</div>
|
|
|
|
<h3 id="toc_0">1. Commit your application to some externally available source control hosting provider.</h3>
|
|
|
|
<p>If you are not doing already, you should host your code somewhere with a
|
|
provuder such as Github, BitBucket, Codeplane, or repositoryhosting.com.</p>
|
|
|
|
<div class="alert-box radius">
|
|
At present Capistrano v3.0.x only supports Git. It's just a matter of time
|
|
until we support Subversion, Mecurial, Darcs and friends again. Please
|
|
contribute if you know these tools well, we don't and don't want to force our
|
|
miscomprehended notions upon anyone.
|
|
</div>
|
|
|
|
<h3 id="toc_1">2. Move secrets out of the repository.</h3>
|
|
|
|
<div class="alert-box alert">
|
|
If you've accidentally committed state secrets to the repository, you might
|
|
want to take <a
|
|
href="https://help.github.com/articles/remove-sensitive-data">special
|
|
steps</a> to erase them from the repository history for all time.
|
|
</div>
|
|
|
|
<p>Ideally one should remove <code>config/database.yml</code> to something like
|
|
<code>config/database.yml.example</code>, you and your team should copy the example file
|
|
into place on their development machines, under Capistrano this leaves the
|
|
<code>database.yml</code> filename unused so that we can symlink the production database
|
|
configuration into place at deploy time.</p>
|
|
|
|
<p>The original <code>database.yml</code> should be added to the <code>.gitignore</code> (or your SCM's
|
|
parallel concept of ignored files)</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-bash'>$ cp config/database.yml{,.example}
|
|
$ echo config/database.yml >> .gitignore</code></pre>
|
|
</div>
|
|
|
|
<p>This should be done for any other secret files, we'll create the production
|
|
version of the file when we deploy, and symlink it into place.</p>
|
|
|
|
<h3 id="toc_2">3. Initialize Capistrano in your application.</h3>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-bash'>$ cd my-project
|
|
$ cap install</code></pre>
|
|
</div>
|
|
|
|
<p>This will create a bunch of files, the important ones are:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-bash'>├── Capfile
|
|
├── config
|
|
│ ├── deploy
|
|
│ │ ├── production.rb
|
|
│ │ └── staging.rb
|
|
│ └── deploy.rb
|
|
└── lib
|
|
└── capistrano
|
|
└── tasks</code></pre>
|
|
</div>
|
|
|
|
<h3 id="toc_3">4. Configure your server addresses in the generated files.</h3>
|
|
|
|
<p>We'll just work with the staging environment here, so you can pretend that
|
|
<code>config/deploy/production.rb</code> doesn't exist, for the most part that's yoru
|
|
business.</p>
|
|
|
|
<p>Capistrano breaks down common tasks into a notion of <em>roles</em>, that is, taking
|
|
a typical Rails application that we have roughly speaking three roles, <code>web</code>,
|
|
<code>app</code>, and <code>db</code>.</p>
|
|
|
|
<p>It can be confusing, as the boundary of web and app servers is a bit blurry if
|
|
using <a href="">Passenger</a> with Apache, which in effect embeds your app server in the
|
|
web server (embeds Passenger in the Apache process itself), confusingly
|
|
Passenger can also be used in modes where this isn't true, so we'll ignore
|
|
that for the time being, and if you know the difference (i.e you are using
|
|
nginx as your web server, and puma/unicorn, or similar for your app server,
|
|
that should be fine) we can assume that they're the same, which is pretty
|
|
common.</p>
|
|
|
|
<p>The example file generated will look something like this:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>set :stage, :staging
|
|
|
|
# Simple Role Syntax
|
|
# ==================
|
|
# Supports bulk-adding hosts to roles, the primary
|
|
# server in each group is considered to be the first
|
|
# unless any hosts have the primary property set.
|
|
role :app, %w{example.com}
|
|
role :web, %w{example.com}
|
|
role :db, %w{example.com}
|
|
|
|
# Extended Server Syntax
|
|
# ======================
|
|
# This can be used to drop a more detailed server
|
|
# definition into the server list. The second argument
|
|
# something that quacks like a has can be used to set
|
|
# extended properties on the server.
|
|
server 'example.com', roles: %w{web app}, my_property: :my_value
|
|
|
|
# set :rails_env, :staging</code></pre>
|
|
</div>
|
|
|
|
<p>Both the simple role, and extended server syntaxes result in one or more
|
|
servers for each role being defined. The <code>app</code> and <code>db</code> roles are just
|
|
placeholders, if you are using the <code>capistrano/rails-*</code> addons (more on
|
|
that later) then they have a meaning, but if you are deploying something
|
|
simpler, feel free to delete them if they're meaningless to you.</p>
|
|
|
|
<p>The extended server syntax exists to allow the definition of arbitrary server
|
|
properties; it's there incase people want to build the server list more
|
|
comprehensively from something like the <em>EC2</em> command line tools, and want to
|
|
use the extended properties for something that makes sense in their
|
|
environment.</p>
|
|
|
|
<p>Servers can be defined in a bunch of ways, the following shows defining two
|
|
servers, one where we set the username, and another where we set the port.
|
|
These host strings are parsed and expanded out in to the equivilent of the
|
|
server line after the comment:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>role :all, %w{hello@world.com example.com:1234}
|
|
# ...is the same as doing...
|
|
server 'world.com' roles: [:web], user: 'hello'
|
|
server 'example.com', roles: [:web], port: 1234</code></pre>
|
|
</div>
|
|
|
|
<h3 id="toc_4">5. Set the shared information in <code>deploy.rb</code>.</h3>
|
|
|
|
<p>The <code>deploy.rb</code> is a place where the configuration common to each environment
|
|
can be specified, normally the <em>repository URL</em> and the <em>user as whom to
|
|
deploy</em> are specified here.</p>
|
|
|
|
<p>The generated sample file starts with the following, and is followed by a few
|
|
self-documenting, commented-out configuration options, feel free to play with
|
|
them a little:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>set :application, 'my app name'
|
|
set :repo, 'git@example.com:me/my_repo.git'
|
|
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }</code></pre>
|
|
</div>
|
|
|
|
<p>Here we'd set the name of the application, ideally in a way that's safe for
|
|
filenames on your target operating system.</p>
|
|
|
|
<p>Second we set the repository URL, this <em>MUST</em> be somewhere that the server we
|
|
are deploying to can reach.</p>
|
|
|
|
<p>Here's how this might look in a typical example, note that we'll cover
|
|
authentication in the next chapter, for now we'll assume this repository is
|
|
open source, we'll take an example application from the <a href="http://railsapps.github.io/">Rails Examples and
|
|
Tutorials</a> site; there we'll find maintained a
|
|
handful of typical Rails apps with typical dependencies.</p>
|
|
|
|
<p>The Rails application they host, which uses Devise (for authentication) and
|
|
Cancan (for authorization) along side Twitter Bootstrap for assets has been
|
|
forked to the Capistrano repository, but you can find the (unchanged) original
|
|
<a href="https://github.com/RailsApps/rails3-bootstrap-devise-cancan">here</a>.</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>set :application, 'rails3-bootstrap-devise-cancan-demo'
|
|
set :repo, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
|
set :branch, 'master'</code></pre>
|
|
</div>
|
|
|
|
<p>I've simplified the <code>:branch</code> varaible to simply be a <code>set</code> varaible, not a
|
|
question prompt, as this repository only has a master branch.</p>
|
|
|
|
<h2 id="toc_5">Roundup</h2>
|
|
|
|
<p><strong>At this point Capistrano knows where to find our servers, and where to find
|
|
our code.</strong></p>
|
|
|
|
<p>We've not covered how we authorise our servers to check out our code (there
|
|
are three pretty good ways of doing that with Git), nor have we determined how
|
|
to authorise Capistrano on our servers yet.</p>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!--<div class="container"> -->
|
|
<!-- <h1 class="title"><a href="/">Capistrano</a></h1>-->
|
|
<!-- <a class="extra" href="/">home</a> -->
|
|
<!-- </div> -->
|
|
|
|
<!-- <div class="alert-box radius">
|
|
This will focus on preparing a Rails application, but most ideas expressed
|
|
here have parallels in Python, or PHP applications
|
|
</div>
|
|
|
|
<h3 id="toc_0">1. Commit your application to some externally available source control hosting provider.</h3>
|
|
|
|
<p>If you are not doing already, you should host your code somewhere with a
|
|
provuder such as Github, BitBucket, Codeplane, or repositoryhosting.com.</p>
|
|
|
|
<div class="alert-box radius">
|
|
At present Capistrano v3.0.x only supports Git. It's just a matter of time
|
|
until we support Subversion, Mecurial, Darcs and friends again. Please
|
|
contribute if you know these tools well, we don't and don't want to force our
|
|
miscomprehended notions upon anyone.
|
|
</div>
|
|
|
|
<h3 id="toc_1">2. Move secrets out of the repository.</h3>
|
|
|
|
<div class="alert-box alert">
|
|
If you've accidentally committed state secrets to the repository, you might
|
|
want to take <a
|
|
href="https://help.github.com/articles/remove-sensitive-data">special
|
|
steps</a> to erase them from the repository history for all time.
|
|
</div>
|
|
|
|
<p>Ideally one should remove <code>config/database.yml</code> to something like
|
|
<code>config/database.yml.example</code>, you and your team should copy the example file
|
|
into place on their development machines, under Capistrano this leaves the
|
|
<code>database.yml</code> filename unused so that we can symlink the production database
|
|
configuration into place at deploy time.</p>
|
|
|
|
<p>The original <code>database.yml</code> should be added to the <code>.gitignore</code> (or your SCM's
|
|
parallel concept of ignored files)</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-bash'>$ cp config/database.yml{,.example}
|
|
$ echo config/database.yml >> .gitignore</code></pre>
|
|
</div>
|
|
|
|
<p>This should be done for any other secret files, we'll create the production
|
|
version of the file when we deploy, and symlink it into place.</p>
|
|
|
|
<h3 id="toc_2">3. Initialize Capistrano in your application.</h3>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-bash'>$ cd my-project
|
|
$ cap install</code></pre>
|
|
</div>
|
|
|
|
<p>This will create a bunch of files, the important ones are:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-bash'>├── Capfile
|
|
├── config
|
|
│ ├── deploy
|
|
│ │ ├── production.rb
|
|
│ │ └── staging.rb
|
|
│ └── deploy.rb
|
|
└── lib
|
|
└── capistrano
|
|
└── tasks</code></pre>
|
|
</div>
|
|
|
|
<h3 id="toc_3">4. Configure your server addresses in the generated files.</h3>
|
|
|
|
<p>We'll just work with the staging environment here, so you can pretend that
|
|
<code>config/deploy/production.rb</code> doesn't exist, for the most part that's yoru
|
|
business.</p>
|
|
|
|
<p>Capistrano breaks down common tasks into a notion of <em>roles</em>, that is, taking
|
|
a typical Rails application that we have roughly speaking three roles, <code>web</code>,
|
|
<code>app</code>, and <code>db</code>.</p>
|
|
|
|
<p>It can be confusing, as the boundary of web and app servers is a bit blurry if
|
|
using <a href="">Passenger</a> with Apache, which in effect embeds your app server in the
|
|
web server (embeds Passenger in the Apache process itself), confusingly
|
|
Passenger can also be used in modes where this isn't true, so we'll ignore
|
|
that for the time being, and if you know the difference (i.e you are using
|
|
nginx as your web server, and puma/unicorn, or similar for your app server,
|
|
that should be fine) we can assume that they're the same, which is pretty
|
|
common.</p>
|
|
|
|
<p>The example file generated will look something like this:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>set :stage, :staging
|
|
|
|
# Simple Role Syntax
|
|
# ==================
|
|
# Supports bulk-adding hosts to roles, the primary
|
|
# server in each group is considered to be the first
|
|
# unless any hosts have the primary property set.
|
|
role :app, %w{example.com}
|
|
role :web, %w{example.com}
|
|
role :db, %w{example.com}
|
|
|
|
# Extended Server Syntax
|
|
# ======================
|
|
# This can be used to drop a more detailed server
|
|
# definition into the server list. The second argument
|
|
# something that quacks like a has can be used to set
|
|
# extended properties on the server.
|
|
server 'example.com', roles: %w{web app}, my_property: :my_value
|
|
|
|
# set :rails_env, :staging</code></pre>
|
|
</div>
|
|
|
|
<p>Both the simple role, and extended server syntaxes result in one or more
|
|
servers for each role being defined. The <code>app</code> and <code>db</code> roles are just
|
|
placeholders, if you are using the <code>capistrano/rails-*</code> addons (more on
|
|
that later) then they have a meaning, but if you are deploying something
|
|
simpler, feel free to delete them if they're meaningless to you.</p>
|
|
|
|
<p>The extended server syntax exists to allow the definition of arbitrary server
|
|
properties; it's there incase people want to build the server list more
|
|
comprehensively from something like the <em>EC2</em> command line tools, and want to
|
|
use the extended properties for something that makes sense in their
|
|
environment.</p>
|
|
|
|
<p>Servers can be defined in a bunch of ways, the following shows defining two
|
|
servers, one where we set the username, and another where we set the port.
|
|
These host strings are parsed and expanded out in to the equivilent of the
|
|
server line after the comment:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>role :all, %w{hello@world.com example.com:1234}
|
|
# ...is the same as doing...
|
|
server 'world.com' roles: [:web], user: 'hello'
|
|
server 'example.com', roles: [:web], port: 1234</code></pre>
|
|
</div>
|
|
|
|
<h3 id="toc_4">5. Set the shared information in <code>deploy.rb</code>.</h3>
|
|
|
|
<p>The <code>deploy.rb</code> is a place where the configuration common to each environment
|
|
can be specified, normally the <em>repository URL</em> and the <em>user as whom to
|
|
deploy</em> are specified here.</p>
|
|
|
|
<p>The generated sample file starts with the following, and is followed by a few
|
|
self-documenting, commented-out configuration options, feel free to play with
|
|
them a little:</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>set :application, 'my app name'
|
|
set :repo, 'git@example.com:me/my_repo.git'
|
|
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }</code></pre>
|
|
</div>
|
|
|
|
<p>Here we'd set the name of the application, ideally in a way that's safe for
|
|
filenames on your target operating system.</p>
|
|
|
|
<p>Second we set the repository URL, this <em>MUST</em> be somewhere that the server we
|
|
are deploying to can reach.</p>
|
|
|
|
<p>Here's how this might look in a typical example, note that we'll cover
|
|
authentication in the next chapter, for now we'll assume this repository is
|
|
open source, we'll take an example application from the <a href="http://railsapps.github.io/">Rails Examples and
|
|
Tutorials</a> site; there we'll find maintained a
|
|
handful of typical Rails apps with typical dependencies.</p>
|
|
|
|
<p>The Rails application they host, which uses Devise (for authentication) and
|
|
Cancan (for authorization) along side Twitter Bootstrap for assets has been
|
|
forked to the Capistrano repository, but you can find the (unchanged) original
|
|
<a href="https://github.com/RailsApps/rails3-bootstrap-devise-cancan">here</a>.</p>
|
|
|
|
<div>
|
|
<pre data-line=''><code class='language-ruby'>set :application, 'rails3-bootstrap-devise-cancan-demo'
|
|
set :repo, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
|
set :branch, 'master'</code></pre>
|
|
</div>
|
|
|
|
<p>I've simplified the <code>:branch</code> varaible to simply be a <code>set</code> varaible, not a
|
|
question prompt, as this repository only has a master branch.</p>
|
|
|
|
<h2 id="toc_5">Roundup</h2>
|
|
|
|
<p><strong>At this point Capistrano knows where to find our servers, and where to find
|
|
our code.</strong></p>
|
|
|
|
<p>We've not covered how we authorise our servers to check out our code (there
|
|
are three pretty good ways of doing that with Git), nor have we determined how
|
|
to authorise Capistrano on our servers yet.</p>
|
|
-->
|
|
|
|
<!--</div> [> /container <] -->
|
|
|
|
<div class="row">
|
|
<div class="large-4 columns">
|
|
<ul>
|
|
<li><a href="/about">About Capistrano</a></li>
|
|
<li><a href="https://github.com/capistrano/capistrano/blob/master/CONTRIBUTING">Contributing</a></li>
|
|
<li><a href="https://rubygems.org/gems/capistrano/versions">Releases</a></li>
|
|
<li><a href="/upgrading">Upgrading</a></li>
|
|
<li><a href="/security">Security</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="large-4 columns">
|
|
<ul>
|
|
<li><a href="http://stackoverflow.com/questions/tagged/capistrano">StackOverflow</a></li>
|
|
<li><a href="https://groups.google.com/forum/#!forum/capistrano">Mailing List</a></li>
|
|
<li><a href=".... ">Commercial Support</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="large-4 columns">
|
|
<ul>
|
|
<li><a href="//twitter.com/capistranorb"><i class="foundicon-twitter"></i></a></li>
|
|
<li><a href="//github.com/capistrano"><i class="foundicon-github"></i></a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script src="/js/prism.js"></script>
|
|
<script src="/js/prism.ruby.js"></script>
|
|
</body>
|
|
</html>
|