【Launchpad】PPAへのアップロード方法

## はじめに

Linuxを使っていると、`sudo apt install`でインストールする機会が多く、自作のアプリもこれでインストール出来るようにしたいと思いました。

しかし、調べたところ、自作のアプリはそのままで`apt`に登録することは出来ないらしく「PPA」を利用することにしました。


### PPAとは？
**Personal Package Archive（PPA）** とは、Ubuntuやその派生ディストリビューションのための非公式なパッケージアーカイブのことです。


通常､`sudo apt install`でインストールできるソフトウェアは公式のUbuntuリポジトリに登録されたものだけであり､**個人が登録することはできません**｡
そこで､個人が登録し､`sudo apt install`でインストールできるようにする仕組みが「**PPA**」｡

PPAを使うには[Launchpad](https://launchpad.net/)に登録します｡
Launchpadは､Ubuntuを開発・保守している「株式会社CANONICAL」が運営しているサービスです｡

### インストール方法
PPAでインストールするには､まずPPAを`sudo add-apt-repository ppa:ユーザー名/PPA名`として､パソコンの`apt`のインストール先に追加します｡
こうすると､`sudo apt install PPA名`で個人登録のソフトウェアをインストールできるようになります｡また､`sudo apt update`や`sudo apt upgrade`を実行した時に巡回してくれて､自動で更新してくれるようにもなります｡


```bash:インストール方法
$ sudo add-apt-repository ppa:yusu79/プロジェクト名
$ sudo apt update && sudo apt install プロジェクト名
```

## 前提
- [Launchpad](https://launchpad.net/)に登録
- GPG鍵の生成と登録
    - [【Launchpad】GPG鍵を登録してPPAを利用する方法 - Qiita](https://qiita.com/yusu79/items/66d1e2d8593edb765917)


## 手順
1. パッケージディレクトリを作る
2. テンプレートとtarボールを作成(`dh_make`) 
3. `debian/`以下を編集
4. ビルド(`dpkg-buildpackage -S -sa`)
5. アップロード(`dput`)

### 1. パッケージディレクトリを作る

ディレクトリ名は「**プロジェクト名_バージョン**」にすること｡

バージョンは､`1.0`などにする｡
```bash:「プロジェクト名」のディレクトリを作る
$ mkdir プロジェクト名_1.0
```

:::note alert
v1.0.0などのように「v」をつけるのは駄目｡
:::

### 2. debianディレクトリ作成(`dh_make`)
プロジェクトパッケージで実行すると、それ以下にLaunchpadへアップロードするためのテンプレートが作られる。

`dh_make`コマンドを使うと自動で､プロジェクトパッケージ以下に`debian/`が作られ､**親ディレクトリ**に`プロジェクト.orig.tar.gz`が作られる｡

:::note info
親ディレクトリにファイルが作成されるコマンドは珍しいが、これで正しい
:::

- `dh_make -s -c 【ライセンス】 --createorig -p 【パッケージディレクトリ】`
  - 現在ディレクトリに`debian/`を､親ディレクトリに`パッケージ.orig.tar.gz`を作成する

```bash:debianディレクトリ作成
$ dh_make -s -c mit --createorig -p プロジェクト名_1.0
$ tree -L 1
.
├── debian
└── プロジェクト名
$ tree .. -L 1
..
├── プロジェクト名_1.0
└── プロジェクト名_1.0.orig.tar.xz
```

### 3.debian/以下の各種ファイルを編集
編集するのは以下の5つのファイル｡
- changelog
- control
- copyright
- rules
- install

#### changelog
changelogはパッケージのバージョン履歴を示すファイル｡

デフォルトでは以下のようになっている｡
```bash:debian/changelog
プロジェクト名 (1.0-1) unstable; urgency=medium

  * Initial release 

 -- ユーザー名 <メールアドレス>  作成日
```
上記の「**unstable**」を自分のPCの**Ubuntuのコードネーム**に変更しなければいけない｡

自分のパソコンの「Ubuntuのコードネーム」を確認するには､以下のコマンドを実行し「`UBUNTU_CODENAME`」を確認する｡
```bash:OSが「Linux Mint」の例
$ cat /etc/os-release
NAME="Linux Mint"
VERSION="20.2 (Uma)"
ID=linuxmint
ID_LIKE=ubuntu
PRETTY_NAME="Linux Mint 20.2"
VERSION_ID="20.2"
HOME_URL="https://www.linuxmint.com/"
SUPPORT_URL="https://forums.linuxmint.com/"
BUG_REPORT_URL="http://linuxmint-troubleshooting-guide.readthedocs.io/en/latest/"
PRIVACY_POLICY_URL="https://www.linuxmint.com/"
VERSION_CODENAME=uma
UBUNTU_CODENAME=focal
```
上記より､Ubuntuのコードネームは「**focal**」であることが分かる｡

後は､「changelog」ファイルを編集する｡
編集するには`dch`コマンドを使う｡
```bash:「dch」を実行すると､エディタが自動起動する
$ dch
```
以下のようになったら､大丈夫｡
```bash:コードネームを「focal」に変更した
プロジェクト名 (1.0-1) focal; urgency=medium

  * Initial release 

 -- yusu79 <メールアドレス>  作成日
```

ちなみに､`urgency`はパッケージ更新の緊急度を表す｡
- low
- medium
- high

#### control
controlファイルは、
- パッケージの概要
- 依存関係
- ビルドに必要なパッケージの情報
 
などを定義するファイル。

```bash:debian/control
Source: プロジェクト名
Section: utils
Priority: optional
Maintainer: yusu79 <メールアドレス>
Build-Depends: debhelper-compat (= 12)
Standards-Version: 4.4.1
Homepage: https://github.com/yusu79/プロジェクト名


Package: プロジェクト名
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Shell script that reads Markdown files and displays them as a tree structure
```

#### copyright
パッケージに含まれるファイルの著作権情報を記述するファイル｡

「プロジェクト名」ではMITライセンスを採用している｡
```bash:debian/copyright
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: プロジェクト名
Upstream-Contact: 2023 yusu79 <メールアドレス>
Source: https://github.com/yusu79/プロジェクト名

Files: *
Copyright: 2023 yusu79 <メールアドレス>
License: MIT

Files: debian/*
Copyright: 2023 yusu79 <メールアドレス>
License: MIT

License: MIT
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:
 .
 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.
 .
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
# Please avoid picking licenses with terms that are more restrictive than the
# packaged work, as it may make Debian's contributions unacceptable upstream.
#
# If you need, there are some extra license texts available in two places:
#   /usr/share/debhelper/dh_make/licenses/
#   /usr/share/common-licenses/
```
- Upstream-Contact
  - Upstream（ソフトウェアの開発元）の連絡先を示すもの
    - ソフトウェアに関する問題を報告したり、ソフトウェアの開発者に問い合わせたりする場合に役立つ
- Source
  - ソフトウェアのソースコードが入手可能な場所を示す
    - つまり､GitHubでOK

#### rules
パッケージをビルドするためのルールを定義するためのファイル｡

今回は､同梱したスクリプトを`usr/bin/`以下にインストールするように指示している｡
```bash:debian/rules
%:
	dh $@

override_dh_auto_install:
	dh_auto_install
	dh_install プロジェクト名 /usr/bin/

```


#### install
`install`ファイルを新規作成して､以下のように書き込むと､`rules`に従い､`プロジェクト名`が「`/usr/bin/`」に格納される｡
```bash:「debian/」に「install」ファイルを新規作成
$ touch install
```
```bash:debian/install
プロジェクト名 usr/bin
```

### 4.ビルド(`dpkg-buildpackage -S -sa`)

まずは､改めて現在ディレクトリと親ディレクトリに「`debian/`」と「`orig.tar.gz`」があるか確認
```bash:現在ディレクトリと親ディレクトリを確認
$ tree -L 1
.
├── debian
└── プロジェクト名
$ tree .. -L 1
..
├── プロジェクト名_1.0
└── プロジェクト名_1.0.orig.tar.xz
```

- `dpkg-buildpackage -S -sa`
  - `.dsc`と`source.buildinfo`と`source.changes`と`debian.tar.xz`の四つのファイルを生成する

この状態で`dpkg-buildpackage -S -sa`を実行すると､GPG鍵のパスワードが問われるので入力する｡すると､以下の四つのファイルが親ディレクトリに生成される｡
- `プロジェクト名_1.0-1.dsc`
- `プロジェクト名_1.0-1_source.buildinfo`
- `プロジェクト名_1.0-1_source.changes`
- `プロジェクト名_1.0-1.debian.tar.xz`

```bash:ビルド実行
$ dpkg-buildpackage -S -sa
$ tree .. -L 1
..
├── プロジェクト名_1.0
├── プロジェクト名_1.0-1.debian.tar.xz
├── プロジェクト名_1.0-1.dsc
├── プロジェクト名_1.0-1_source.buildinfo
├── プロジェクト名_1.0-1_source.changes
└── プロジェクト名_1.0.orig.tar.xz
```



### 5.PPAにアップロード(`dput`)
PPAにアップロードするには`dput`コマンドを使う｡

それからここが一番重要だが､アップロードするのは「**source.changes**」ファイルのみ｡

- `dput ppa:ユーザー名/PPA source.changes`
  - PPAにアップロード

```bash:「プロジェクト名」をアップロード
$ dput ppa:yusu79/プロジェクト名 プロジェクト名_1.0-1_source.changes
```
これでアップロードが完了し､PPAをインストールできるようになった｡


## 補足

### インストール
```bash:インストール
$ sudo add-apt-repository ppa:yusu79/プロジェクト名
$ sudo apt update && sudo apt install プロジェクト名
```

### アンインストール
```bash:アンインストール
$ sudo apt remove プロジェクト名
```

### PPA一覧確認
```bash:PPAの一覧確認
ls -1 /etc/apt/sources.list.d
```
```bash:PPAマネージャー起動
y-ppa-manager
```

### PPA削除
```bash:「プロジェクト名」PPAを削除
$ sudo add-apt-repository --remove ppa:yusu79/プロジェクト名
```

## まとめ
これで、誰でも`sudo add-apt-repository ppa:ユーザー名/プロジェクト名`でPPAを登録してインストールできるようになります。