aboutsummaryrefslogtreecommitdiffstats
path: root/shipper/shipper.xml
blob: 765f0f54fc264ffaa3b7a3b268fda2e66b621a26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
<!DOCTYPE refentry PUBLIC 
   "-//OASIS//DTD DocBook XML V4.1.2//EN"
   "docbook/docbookx.dtd">
<refentry id='shipper.1'>
<refmeta>
<refentrytitle>shipper</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv id='name'>
<refname> shipper</refname>
<refpurpose>automatic drop-shipping of project releases</refpurpose>
</refnamediv>
<refsynopsisdiv id='synopsis'>

<cmdsynopsis>
  <command>shipper</command>  
  <arg choice='opt'>-h</arg>
  <arg choice='opt'>-n</arg>
  <arg choice='opt'>-N</arg>
  <arg choice='opt'>-f</arg>
  <arg choice='opt'>-v</arg>
</cmdsynopsis>
<cmdsynopsis>
  <command>buildrpms</command>
  <arg choice='req'><replaceable>tarball</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>

<refsect1><title>Description</title>

<para><application>shipper</application> is a tool for shipping
project releases.  Its job is to make it possible for you to run the
command <command>shipper</command> in the top-level directory of a
project and have a release be properly exported to all the places that
you normally deliver it &mdash; your personal website, Linux source
code archive sites, and distribution submission queues. A second goal
is to arrange your shipping process in such a way that metadata like
your project version only have to be kept in one place and modified
once per release. The overall goal is to reduce the friction cost
of shipping releases to as near zero as possible.</para>

<para><application>buildrpms</application> is a helper script that
builds source and binary RPMs from a specified tarball with a
BuildRoot field. <application>shipper</application> also calls
<citerefentry>
<refentrytitle>rpm2lsm</refentrytitle>
<manvolnum>1</manvolnum></citerefentry> to do part of its work.</para>

<para>As much as possible, <application>shipper</application> tries to
deduce what it should do rather than requiring you to tell it.  In
order to do this, it relies on your project obeying standard GNU-like
naming conventions.  It also relies on being able to mine project
metadata out of a package specfile.  (Presently the only variety of
package specfile supported is an RPM spec; this may change in the future,
when we fully support shipping Debian packages.)</para>

<para>In normal use, you need set only one configuration variable,
which is the list of private destinations to ship to.  You may also
want to add some magic <quote>Keywords</quote> comments to your
project specfiles.  Once you have <application>shipper</application>
up and running, you can experiment with more advanced features
such as having the program generate project web pages for you.</para>
</refsect1>

<refsect1><title>Theory of Operation</title>

<para><application>shipper</application> pushes
<emphasis>deliverables</emphasis> out to
<emphasis>destinations</emphasis>.  Deliverables include: source tarballs,
source zip archives, source RPMs, binary RPMs, ChangeLog files, README
files, LSM files, and various other project metadata files.  Destinations
include both <emphasis>private destinations</emphasis> like websites, FTP
archive sites and mailing lists, and <emphasis>public
channels</emphasis> like ibiblio, freshmeat.net, and the submission
queues for various well-known operating-system distributions. The
shipper framework is extensible and it is relatively easy to add new
channel types and new deliverables; in the future, we hope to support
(for example) Debian packages as deliverables and SourceForge as a
channel.</para>

<para><application>shipper</application>'s first step is to find the
project name and version, then to check that the minimum set of files that
<application>shipper</application> requires to continue is in place.
To start with, <application>shipper</application> needs a source
tarball and a specfile. Once it knows those are in place, it
can extract various pieces of information it will need to do its
real work. It also reads in a handful of configuration variables.
The -N (nobuild) option causes it to dump all configuration values and
stop there.</para>

<para>The first real work that gets done is finding or building local
deliverables.  These are either <emphasis>generated
deliverables</emphasis> (like RPMs) that can be rebuilt automatically,
or or <emphasis>stock deliverables</emphasis> (like a README file)
that have to be changed by hand.  <application>shipper</application>
rebuilds any generated deliverable that doesn't exist when it starts
up.  Building local deliverables is separated from uploading because
it means that you can stop and inspect what you're going to ship
before committing to an upload.</para>

<para>The -n (noupload) option stops before uploading, leaving all
local deliverables in place but displaying the exact upload commands
that would have been used to ship them.  The -f (force) option forces
a rebuild of all generated deliverables, even those that already
exist.  The command <command>shipper -f -n</command> will show you
exactly what <application>shipper</application> would do for a real
upload.</para>

<para>Once all local deliverables have been built,
<application>shipper</application> can begin uploading files and
posting announcements. It does private destinations first, then public
channels.  This means, for example, that if you give
<application>shipper</application> your personal website as a destination, the
website will get updated each time <emphasis>before</emphasis>
any submissions or announcements are sent to public sites like 
ibiblio.org or freshmeat.net.</para>

<para>When uploads are complete, <application>shipper</application>
cleans up after itself by deleting any deliverables it created for
this run.  Deliverables that were found and up to date are not
removed.</para>

<para>Finally, note that <application>shipper</application> makes one
important assumption about the structure of your website(s).  Beneath
each directory in your <varname>destinations</varname> list, there
will be one subdirectory for each project, with the directory leaf
name being the same as the project.  Thus, for example, if you have
three projects named ruby, diamond and sapphire, and your personal
site is at <filename>gemstones.net:/public/www/precious/</filename>,
<application>shipper</application> will expect to be able to drop
deliverables in three directories
<filename>gemstones.net:/public/www/precious/ruby</filename>,
<filename>gemstones.net:/public/www/precious/diamond/</filename>, and
<filename>gemstones.net:/public/www/precious/sapphire/</filename>.
Note that <application>shipper</application> will not create these
project directories for you if they're missing; this is deliberate, so
that uploads to sites that are not prepared for them will fail
noisily.</para>

</refsect1>

<refsect1><title>How Shipper Deduces What To Do</title>

<para>The behavior of shipper depends on a handful of internal
variables.  Some of these variables have defaults computed at startup
time.  All can be set or overridden in the per-user
<filename>~/.shipper</filename> file, and overridden in any
per-project <filename>.shipper</filename> file.  Both files are Python
code and the syntax of variable settings is Python's.</para>

<para>If a variable is set in a config file, that value is locked in
(except for the <varname>destinations</varname> variable which can be
appended to from a specfile, see below) Variables that are
<emphasis>not</emphasis> set in a config file may be set by the values
of fields in your project specfile.</para>

<para>For basic use, it is only necessary to set one such variable:
<varname>destinations</varname>, the list of destinations to ship to.
Normally you'll set this globally, pointing all your projects at your
main distribution website, in your <filename>~/.shipper</filename>
file; it is also possible to add destinations on a per-project basis
by giving a comma-separated list in a #Destinations: comment in the
specfile.  You can set the variable in a per-project
<filename>.shipper</filename> to ignore your global destination
list.</para>

<para>The first thing shipper looks for is a specfile in the
current directory; there must be exactly one.  It extracts the project
name from the Name field.  Next step is to find the project version
(the variable <varname>package</varname>).  This is extracted from the
specfile, or by looking for a makefile macro with a name
beginning with VERS; if the value of that macro is a shell command
wrapped in $(shell ...), it is executed and the output is captured to
yield the version.  If both versions are present, they are
consistency-checked.</para>

<para><application>shipper</application> gets most of the rest of the
data it uses to decide what to do from headers in the specfile.
The following table lists all the variables and their corresponding
specfile fields. <application>shipper</application> uses the RPM spec
file fields: the Debian entries are informational only.</para>

<informaltable>
<tgroup cols="4">
<thead>
<row>
<entry>Variable</entry>
<entry>RPM specfile field</entry>
<entry>Debian specfile field</entry>
<entry>Meaning</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>destinations</varname></entry>
<entry>#Destinations:</entry>
<entry>XBS-Destinations:</entry>
<entry>
<para>A list of remote directories to ship to using
<citerefentry>
<refentrytitle>scp</refentrytitle> <manvolnum>1</manvolnum>
</citerefentry>.  Each location is a place to drop deliverables:
either a [user@]site:path destination that
<citerefentry>
<refentrytitle>scp</refentrytitle> <manvolnum>1</manvolnum>
</citerefentry> can use, or an FTP url that
<citerefentry>
<refentrytitle>lftp</refentrytitle> <manvolnum>1</manvolnum>
</citerefentry>
can use. Note that actual project directories are computed by
appending the value of <varname>package</varname> to
the destination you're shipping to.</para>

<para><emphasis role='bold'>There is no default.</emphasis>.  If you
do not set this variable, <application>shipper</application> will
ship only to public channels.</para>
</entry>
</row>
<row>
<entry><varname>channels</varname></entry>
<entry align='center'>-</entry>
<entry align='center'>-</entry>
<entry>
<para>The list of public channels to be shipped to after the private
channels in the <varname>destination</varname> list. You can disable
one or more of these in a config file by calling the function
<function>disable()</function>; for example with
<command>disable('freshmeat')</command>.</para>
</entry>
</row>
<row>
<entry><varname>whoami</varname></entry>
<entry align='center'>-</entry>
<entry align='center'>-</entry>
<entry>
<para>A plausible email address for the user.  If not specified in the
config file, it's generated from
<envar>$USERNAME</envar> and <envar>$HOSTNAME</envar>.</para>
</entry>
</row>
<row>
<entry><varname>date</varname></entry>
<entry align='center'>-</entry>
<entry align='center'>-</entry>
<entry>
<para>The program's startup time. This can be used in the web page and
email announcement templates.</para>

<para>You can use the Python function time.strftime("...") in your
<filename>~/.shipper</filename> file to format this date to your
taste.  If you don't set this in the config file, the program will
set it for you.</para>
</entry>
</row>
<row>
<entry><varname>indextemplate</varname></entry>
<entry align='center'>-</entry>
<entry align='center'>-</entry>
<entry>
<para>Template HTML from which to generate index.html for shipping.  There is a
default which generates a very simple page containing a title, a 
date, and a table listing downloadable resources.  This is used when
shipping to a web directory, if no index page exists when shipper
is run.</para>
</entry>
</row>
<row>
<entry><varname>mailtemplate</varname></entry>
<entry align='center'>-</entry>
<entry align='center'>-</entry>
<entry>
<para>Template text from which to generate the file ANNOUNCE.EMAIL to be
shipped to destinations that are mailto URLs.  There is a default which
generates a very simple email containing a subject, a pointer to the 
project web page, and the last entry in the project changelog.</para>
</entry>
</row>
<row>
<entry><varname>package</varname></entry>
<entry>Name:</entry>
<entry>Package:</entry>
<entry>
<para>Project name, used to generate the stem part of the names of RPMs and
other deliverables that <application>shipper</application>
builds. If the specfile is a Debian control file, the Debian-specific
part of the version number (after the dash) is removed.</para>
</entry>
</row>
<row>
<entry><varname>version</varname></entry>
<entry>Version:</entry>
<entry>Version:</entry>
<entry>
<para>Project version, used in generating the names of RPMs and
other deliverables that <application>shipper</application>
builds.</para>
</entry>
</row>
<row>
<entry><varname>homepage</varname></entry>
<entry>URL:</entry>
<entry>XBS-Home-Page:</entry>
<entry>
<para>Project home page URL. Used when generating project 
announcements.</para>
</entry>
</row>
<row>
<entry><varname>arch</varname></entry>
<entry>BuildArch:</entry>
<entry>Architecture:</entry>
<entry>
<para>Build architecture.  If this field is <quote>noarch</quote>, 
noarch rather than binary RPMs will be built.</para>
</entry>
</row>
<row>
<entry><varname>keywords</varname></entry>
<entry>#Keywords:</entry>
<entry>XBS-Keywords:</entry>
<entry>
<para>Topic keywords. Used when generating LSM files.</para>
</entry>
</row>
<row>
<entry><varname>freshmeat_name</varname></entry>
<entry>#Freshmeat-Name:</entry>
<entry>XBS-Freshmeat-Name:</entry>
<entry>
<para>Freshmeat shortname, used in generating freshmeat.net
announcements. If this isn't present, it defaults to the project
name; you only need to set it if they differ.</para>
</entry>
</row>
<row>
<entry><varname>summary</varname></entry>
<entry>Summary</entry>
<entry>Description:</entry>
<entry>
<para>The one-line project summary field from your specfile.</para>
</entry>
</row>
<row>
<entry><varname>description</varname></entry>
<entry>%description</entry>
<entry>Description:</entry>
<entry>
<para>The Description field from your specfile.</para>
</entry>
</row>
<row>
<entry><varname>changelog</varname></entry>
<entry>ChangeLog or %changelog</entry>
<entry align='center'>-</entry>
<entry>
<para>If a <filename>ChangeLog</filename> file exists in the project
directory, its entire contents.  Otherwise, if it exists,
the entire changelog section from the specfile.</para>
</entry>
</row>
<row>
<entry><varname>lastchange</varname></entry>
<entry>ChangeLog or %changelog</entry>
<entry align='center'>-</entry>
<entry>
<para>
If the source of your changlog was your specfile, this is the
most recent entry from your changelog without
its date/author/release header.  If the source was Changelog, a 
line of text directing the user to see the ChangeLog file. 
This becomes the Changes field in your freshmeat.net announcement,
and freshmeat.net doesn't like the bulleted format of GNU ChangeLog
entries.</para>
</entry>
</row>
<row>
<entry><varname>resourcetable</varname></entry> <entry
align='center'>-</entry> <entry align='center'>-</entry>
<entry>
<para>The HTML table of links to downloadable resources.  This
variable is only computed if the index page is built.  Any setting
of it in the startup files is ignored.</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>

<para>All these variables are available for substitution at the time a
web page or email announcement is generated. In general, any variable
you set in your <filename>~/.shipper</filename> file will be available
at the time the web page or email announcement is generated.  Use the
Python "%(variable)s" syntax, not shell-substitution syntax.</para>

</refsect1>

<refsect1><title>Finding and Building Local Deliverables</title>

<para>The following files are considered stock deliverables and may be
shipped if they are present when <application>shipper</application>
starts up:</para>

<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>File</entry>
<entry>Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry>README</entry>
<entry>
<para>Project roadmap file.</para>
</entry>
</row>
<row>
<entry>tarball</entry>
<entry>
<para>The current source tarball, that is the file named ${package}-${version}.tar.gz.</para>
</entry>
</row>
<row>
<entry>zipfile</entry>
<entry>
<para>The current source zip archive, that is the file named ${package}-${version}.zip.</para>
</entry>
</row>
<row>
<entry>NEWS</entry>
<entry>
<para>Project news file.</para>
</entry>
</row>
<row>
<entry>ChangeLog</entry>
<entry>
<para>Project change log.</para>
</entry>
</row>
<row>
<entry>HISTORY</entry>
<entry>
<para>Project history file.</para>
</entry>
</row>
<row>
<entry>BUGS</entry>
<entry>
<para>Project bug list.</para>
</entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<para>Current to-do list.</para>
</entry>
</row>
<row>
<entry>*.html</entry>
<entry>
<para>Any files with an .html extension will be shipped to all 
website destinations.</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>

<para>Here are the generated deliverables that
<application>shipper</application> will build and ship, if they don't
exist when it starts up.  Any of these that are created will be 
deleted after a successful upload.</para>

<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Type</entry>
<entry>Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry>index.html</entry>
<entry>
<para>An index web page, to be shipped to any website destination.</para>
</entry>
</row>
<row>
<entry>RPMs</entry>
<entry>
<para>Source and either binary or noarch RPMs.</para>
</entry>
</row>
<row>
<entry>LSM</entry>
<entry>
<para>If the ibiblio channel is enabled,
<application>shipper</application> will generate a Linux Software Map
file for it.</para>
</entry>
</row>
<row>
<entry>CHANGES</entry>
<entry>
<para>If there is no ChangeLog file but there was a %changelog in your
specfile, <application>shipper</application> will generate a CHANGES
from the changelog entries in the specfile and ship that.</para>
</entry>
</row>
<row>
<entry>ANNOUNCE.FRESHMEAT</entry>
<entry>
<para>If there is no ANNOUNCE.FRESHMEAT file,
<application>shipper</application> will generate one. It will be a
job card that can be fed to freshmeat.net's XML-RPC interface via
<citerefentry><refentrytitle>freshmeat-submit</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para>
</entry>
</row>
<row>
<entry>ANNOUNCE.EMAIL</entry>
<entry>
<para>If there is no ANNOUNCE.EMAIL file, <application>shipper</application>
will generate one to be emailed to destinations that are mailto URLs.</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</refsect1>

<refsect1><title>Shipping to Destinations</title>
<para>In operation, <application>shipper</application> walks through a
list of destinations, building the required deliverables for each one and
performing the required shipping actions to push them out to the
destination.  Here are the channel types
<application>shipper</application> knows about:</para>

<informaltable>
<tgroup cols="4">
<colspec align='left'/>
<colspec align='left'/>
<colspec align='center'/>
<colspec align='left'/>
<thead>
<row>
<entry>Channel Type</entry>
<entry>Deliverables</entry>
<entry>Specified by</entry>
<entry>Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry>ibiblio</entry>
<entry>tarball, RPMs, LSM file</entry>
<entry>-</entry>
<entry>
<para>If the ibiblio channel is enabled (it is by default),
<application>shipper</application> will attempt to ship a source
tarball, RPMs, and an an LSM file to ibiblio.org via FTP.  The LSM
file will be automatically generated.</para>
</entry>
</row>
<row>
<entry>redhat</entry>
<entry>RPMs</entry>
<entry>-</entry>
<entry>
<para>If the Red Hat channel is enabled (it is by default),
<application>shipper</application> will attempt to ship source
and binary RPMs to the Red Hat submission directory via FTP.</para>
</entry>
</row>
<row>
<entry>freshmeat</entry>
<entry>ANNOUNCE.FRESHMEAT</entry>
<entry>-</entry>
<entry>
<para>If the freshmeat channel is enabled (it is by default),
<application>shipper</application> will attempt to post a release
announcement on freshmeat.net using
<citerefentry><refentrytitle>freshmeat-submit</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
The
announcement will include URLs for whichever of the following
deliverables are shipped, using the URL field from your specfile: tarball,
zipfile, RPMs, CHANGES.  The user will be
prompted for a Freshmeat release-focus.  This announcement is
generated into the local deliverable ANNOUNCE.FRESHMEAT.</para>
</entry>
</row>
<row>
<entry>Generic Web site</entry>
<entry>README, tarball, zipfile, RPMs, CHANGES, NEWS, HISTORY, *.html, 
BUGS, TODO.</entry>
<entry>scp destination ([user@]host:dir)</entry>
<entry>
<para>This channel type represents a website.
<application>shipper</application> uses
<citerefentry><refentrytitle>scp</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to put deliverables on websites.  If the user part of the scp
destination is absent, it will be taken from the environment variable
<envar>USERNAME</envar>.</para>

<para>No generic Web sites are shipped to by default. You must declare
them by putting scp destinations in the <varname>destinations</varname>
variable.</para>
</entry>
</row>
<row>
<entry>Generic FTP site</entry>
<entry>tarball, RPMs</entry>
<entry>FTP URL</entry>
<entry>
<para>Old-fashioned FTP site with no metadata.  The FTP URL is parsed
to get the sitename and directory where deliverables should be dropped.  The
FTP username to be used will be taken from the environment variable
<envar>USERNAME</envar>.  The FTP password will be looked up in your
<filename>~/.netrc</filename> file.</para>

<para>No generic FTP sites are shipped to by default.  You must
declare them by putting FTP urls in the
<varname>destinations</varname> variable.</para>
</entry>
</row>
<row>
<entry>Email address</entry>
<entry>ANNOUNCE.EMAIL</entry>
<entry>mailto URL</entry>
<entry>
<para>The contents of the generated ANNOUNCE.EMAIL file is emailed to
each email address specified as a channel.</para>

<para>No email channels are set up by default.  You must
declare them by putting mailto: urls in the
<varname>destinations</varname> variable.</para>
</entry>
</row>
<row>
<entry>rsync unit</entry>
<entry>SRPM</entry>
<entry>rsync address ([user@]host::unit)</entry>
<entry>
<para>An SRPM is shipped to each destination that is rcognized as 
an rsync address (by the double colon).</para>

<para>No rsync channels are set up by default.  You must
declare them by putting rsync addresses in the
<varname>destinations</varname> variable.</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</refsect1>

<refsect1><title>Command-line Options</title>

<para>The -n option of <application>shipper</application> suppresses
uploads, just building all deliverables locally.  The -N option
suppresses both uploads and builds, generating a configuration dumop
instead.  The -f option forces rebuilding of local deliverables even
if they already exist.  The -v option makes
<application>shipper</application> chatty about what it's doing.  The
-h option prints a usage message and exits.</para>

</refsect1>

<refsect1><title>Hints and Tips</title>
<para>The following variable definition in your makefile will ensure
that the makefile version is derived from (and thus always consistent
with) the specfile version.</para>

<programlisting>
VERS=$(shell sed &lt;*.spec -n -e '/Version: \(.*\)/s//\1/p')
</programlisting>

<para>A makefile production like the following will allow
you to type <command>make release</command> and be sure that all
the deliverables <application>shipper</application> knows about
will be rebuilt before being shipped.</para>

<programlisting>
release: <emphasis>package</emphasis>-$(VERS).tar.gz <emphasis>package</emphasis>.html 
	shipper -f
</programlisting>

<para>You will want to change <emphasis>package</emphasis> to your 
project name.  Note that you should not use this recipe if your
project  has its own (non-generated) index page, as the -f option will
overwrite <filename>index.html</filename>.</para>

<para>To make
<citerefentry>
<refentrytitle>rpm</refentrytitle><manvolnum>1</manvolnum>
</citerefentry>
build noarch rather than binary RPMs, insert the following header in
your specfile:</para>

<programlisting>
BuildArch: noarch
</programlisting>
</refsect1>

<refsect1><title>Author</title>
<para>Eric S. Raymond <email>esr@thyrsus.com</email>.  The buildrpms
script was originally by Sean Reifschneider.</para>

<para>There is a project web page at
<ulink
url="http://www.catb.org/~esr/shipper/">http://www.catb.org/~esr/shipper/</ulink>.</para>
</refsect1>

<refsect1><title>Bugs</title>
<para>The rsync channel type is untested.  Shipping Debian packages 
should be supported.</para>
</refsect1>

<refsect1><title>See Also</title>

<para>
<citerefentry>
<refentrytitle>freshmeat-submit</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>lftp</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>rpm2lsm</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>scp</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>ssh</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>.</para>
</refsect1>
</refentry>

<!--
Local Variables:
compile-command: "make shipper.html"
End:
-->