Jaypore CI

> Jaypore CI: Minimal, Offline, Local CI system.
Log | Files | Refs | README | LICENSE

README.md (4523B)


      1 # Example 07 — Secrets with SOPS + Telegram
      2 
      3 This Jaypore CI example shows how to keep secrets (API tokens, credentials)
      4 encrypted inside your repository using [Mozilla SOPS](https://github.com/getsops/sops)
      5 and decrypt them at CI time. The decrypted values are used to send a Telegram
      6 notification with the build result.
      7 
      8 ## How it works
      9 
     10 | Step | What happens |
     11 |------|-------------|
     12 | 1 | If `sops` is installed and `secrets.enc.json` exists, decrypt it to obtain `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID`. |
     13 | 2 | If SOPS is unavailable, fall back to plain environment variables. |
     14 | 3 | Run `python3 manage.py test core` and capture the result. |
     15 | 4 | Send a Markdown-formatted message to Telegram with the build status. |
     16 | 5 | Save all artifacts to `$JCI_OUTPUT_DIR`. |
     17 
     18 ## Artifacts produced
     19 
     20 | File | Description |
     21 |------|-------------|
     22 | `test_output.txt` | Full test output. |
     23 | `exit_code.txt` | Exit code from the test run. |
     24 | `telegram_response.json` | Telegram API response (when notification is sent). |
     25 
     26 ## Setting up SOPS
     27 
     28 ### 1. Install SOPS
     29 
     30 ```bash
     31 # Debian / Ubuntu
     32 curl -LO https://github.com/getsops/sops/releases/download/v3.9.4/sops_3.9.4_amd64.deb
     33 sudo dpkg -i sops_3.9.4_amd64.deb
     34 
     35 # macOS
     36 brew install sops
     37 ```
     38 
     39 ### 2. Choose an encryption backend
     40 
     41 SOPS supports **age**, **GPG**, **AWS KMS**, **GCP KMS**, and **Azure Key Vault**.
     42 For local / small-team use, [age](https://github.com/FiloSottile/age) is the
     43 simplest option:
     44 
     45 ```bash
     46 # Install age
     47 sudo apt install age        # Debian/Ubuntu
     48 brew install age            # macOS
     49 
     50 # Generate a key pair
     51 age-keygen -o ~/.config/sops/age/keys.txt
     52 # Note the public key printed to stdout (starts with "age1...")
     53 ```
     54 
     55 ### 3. Create a `.sops.yaml` config (optional but recommended)
     56 
     57 Place this in your repository root so SOPS knows which key to use:
     58 
     59 ```yaml
     60 creation_rules:
     61   - path_regex: secrets\.enc\.json$
     62     age: "age1your-public-key-here"
     63 ```
     64 
     65 ### 4. Create and encrypt the secrets file
     66 
     67 Start from the provided template:
     68 
     69 ```bash
     70 cp secrets.example.json secrets.json
     71 ```
     72 
     73 Edit `secrets.json` with your real values:
     74 
     75 ```json
     76 {
     77     "TELEGRAM_BOT_TOKEN": "123456789:ABCdefGHI-JKLmnoPQRstUVwxyz",
     78     "TELEGRAM_CHAT_ID": "-1001234567890"
     79 }
     80 ```
     81 
     82 Encrypt it:
     83 
     84 ```bash
     85 sops -e secrets.json > secrets.enc.json
     86 ```
     87 
     88 Now commit `secrets.enc.json` (the encrypted version) and **delete the
     89 plaintext** `secrets.json`:
     90 
     91 ```bash
     92 rm secrets.json
     93 git add secrets.enc.json
     94 git commit -m "Add encrypted secrets"
     95 ```
     96 
     97 > **Never commit the plaintext `secrets.json`.**  Add it to `.gitignore`.
     98 
     99 ### 5. Decrypt (what run.sh does)
    100 
    101 At CI time the script runs:
    102 
    103 ```bash
    104 sops -d secrets.enc.json
    105 ```
    106 
    107 This prints the decrypted JSON to stdout. The script parses it with Python to
    108 extract individual values into environment variables.
    109 
    110 Decryption requires the private key. For `age`, the key file at
    111 `~/.config/sops/age/keys.txt` is used automatically.
    112 
    113 ## Alternative: plain environment variables
    114 
    115 If you prefer not to use SOPS, export the variables before running CI:
    116 
    117 ```bash
    118 export TELEGRAM_BOT_TOKEN="123456789:ABCdefGHI-JKLmnoPQRstUVwxyz"
    119 export TELEGRAM_CHAT_ID="-1001234567890"
    120 git jci run
    121 ```
    122 
    123 The script detects that SOPS is absent (or that the encrypted file is missing)
    124 and falls back to whatever `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` are
    125 already set in the environment.
    126 
    127 ## Setting up Telegram
    128 
    129 1. Create a bot via [BotFather](https://t.me/BotFather) and note the **bot
    130    token**.
    131 2. Get your **chat ID** by sending a message to the bot and visiting
    132    `https://api.telegram.org/bot<TOKEN>/getUpdates`.
    133 3. Put both values into `secrets.json` and encrypt with SOPS (see above), or
    134    export them as environment variables.
    135 
    136 ## Project layout
    137 
    138 ```
    139 your-repo/
    140 ├── manage.py
    141 ├── mysite/
    142 │   └── settings.py
    143 ├── core/                    # the Django app under test
    144 ├── secrets.enc.json         # encrypted secrets (committed)
    145 ├── secrets.example.json     # template with placeholder values
    146 ├── .sops.yaml               # SOPS config (optional)
    147 └── .jci/
    148     └── run.sh               # ← this script
    149 ```
    150 
    151 ## How to use
    152 
    153 1. Copy the `.jci/` directory and `secrets.example.json` into your repo:
    154 
    155    ```bash
    156    cp -r 07-secrets-telegram/.jci /path/to/your-repo/.jci
    157    cp 07-secrets-telegram/secrets.example.json /path/to/your-repo/
    158    ```
    159 
    160 2. Set up SOPS and encrypt your secrets (see above), or export them as
    161    environment variables.
    162 
    163 3. Run Jaypore CI:
    164 
    165    ```bash
    166    git jci run
    167    ```