├── .dockerignore
├── .github
└── workflows
│ └── lint.yml
├── .gitignore
├── .terraform.lock.hcl
├── .tflint.hcl
├── README.md
├── libvirt-domain.xsl
├── main.tf
├── qemu-agent-guest-exec
├── renovate.json5
└── renovate.sh
/.dockerignore:
--------------------------------------------------------------------------------
1 | *
2 | !requirements.txt
3 | !requirements.yml
4 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 | on: [push]
3 | jobs:
4 | lint:
5 | name: Lint
6 | runs-on: ubuntu-22.04
7 | steps:
8 | - uses: actions/checkout@v4
9 | - name: Cache the plugins directory
10 | uses: actions/cache@v4
11 | with:
12 | path: ~/.tflint.d/plugins
13 | key: tflint-${{ hashFiles('.tflint.hcl') }}
14 | - uses: terraform-linters/setup-tflint@v4
15 | name: Setup
16 | with:
17 | # see https://github.com/terraform-linters/tflint/releases
18 | # renovate: datasource=github-releases depName=terraform-linters/tflint
19 | tflint_version: v0.52.0
20 | - name: Init
21 | run: tflint --init
22 | env:
23 | # https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/plugins.md#avoiding-rate-limiting
24 | GITHUB_TOKEN: ${{ github.token }}
25 | - name: Lint
26 | run: tflint --format compact
27 | fmt:
28 | name: terraform fmt check
29 | runs-on: ubuntu-22.04
30 | steps:
31 | - uses: actions/checkout@v4
32 | - name: terraform fmt check
33 | run: terraform fmt -check -diff
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | tmp/
2 | .terraform/
3 | *terraform.tfstate*
4 | tfplan
5 |
--------------------------------------------------------------------------------
/.terraform.lock.hcl:
--------------------------------------------------------------------------------
1 | # This file is maintained automatically by "terraform init".
2 | # Manual edits may be lost in future updates.
3 |
4 | provider "registry.terraform.io/dmacvicar/libvirt" {
5 | version = "0.7.6"
6 | constraints = "0.7.6"
7 | hashes = [
8 | "h1:mmbm4vTyC/DCGO4Ed/vbp5AKvy1gmVn/94fzB9VmR08=",
9 | "zh:0bde54f6f658b20b620b875daf106b5b25b1bae4d15408d6c5f06d58360e254d",
10 | "zh:0c97c6930015918b8a34b6d7a2b0c3d17a649c226fcd1874fcba5bbbc0f35972",
11 | "zh:1bdd7aa0011c5f024a09a124836ee9bc8e71b05a6ece810c61824275fd3f695f",
12 | "zh:2b0cc7c794e4caf395d84ffff0b380d17e4b3219a4696264271bfe5059450efe",
13 | "zh:2f8633f7fe07f76c188836ed6f93321ec5fbf5c004bc7699e1741d9b21ed5f37",
14 | "zh:5bf47eed286ce55ed10a5cf657de49a34ab21cc8677c56fef3aab69cdde41a27",
15 | "zh:7dca790fc5fd1d42bc4bc7170be003a7093602026d0f95c8aab84ad551fdf2a4",
16 | "zh:80476b68bc84e3d661d1390025f83879b88f9cdc836de9751af09bd5716089cb",
17 | "zh:82f3e2f3f50176cd6041c8ba36e295cbda1b289ef52ab75b5eceb0f921f64f7b",
18 | "zh:a179b165f3b9bb9a67ebbbf9d73157ded33f02d476b2f58906389dca03b653c9",
19 | "zh:acae54a5d0616f22b3180ddd8e8aad39af664e604394fdacf1f7b337bca2d5b4",
20 | "zh:da4406a2428a9a7e98272c032cb93431c3919253af2fe9934b532d26c0deab09",
21 | "zh:f63dbd8e579ab5268d01ffab4503b8a8e736b70d1a04e4f271559ba8dd133dcd",
22 | "zh:f85c1d9e51a94ecde137435c9d6b0fb7be590437ea8a725334d1577eebbc550c",
23 | ]
24 | }
25 |
26 | provider "registry.terraform.io/hashicorp/random" {
27 | version = "3.6.2"
28 | constraints = "3.6.2"
29 | hashes = [
30 | "h1:wmG0QFjQ2OfyPy6BB7mQ57WtoZZGGV07uAPQeDmIrAE=",
31 | "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec",
32 | "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53",
33 | "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114",
34 | "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad",
35 | "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b",
36 | "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916",
37 | "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6",
38 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
39 | "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150",
40 | "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544",
41 | "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7",
42 | "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af",
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/.tflint.hcl:
--------------------------------------------------------------------------------
1 | # NB the terraform plugin is built into tflint, so no need to declare it here.
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Usage (Ubuntu 22.04 host)
2 |
3 | [](https://github.com/rgl/terraform-libvirt-ubuntu-example/actions/workflows/lint.yml)
4 |
5 | Create and install the [base Ubuntu 22.04 vagrant box](https://github.com/rgl/ubuntu-vagrant).
6 |
7 | Install Terraform:
8 |
9 | ```bash
10 | wget https://releases.hashicorp.com/terraform/1.9.2/terraform_1.9.2_linux_amd64.zip
11 | unzip terraform_1.9.2_linux_amd64.zip
12 | sudo install terraform /usr/local/bin
13 | rm terraform terraform_*_linux_amd64.zip
14 | ```
15 |
16 | Create the infrastructure:
17 |
18 | ```bash
19 | export CHECKPOINT_DISABLE=1
20 | export TF_LOG=TRACE
21 | export TF_LOG_PATH="$PWD/terraform.log"
22 | terraform init
23 | terraform plan -out=tfplan
24 | time terraform apply tfplan
25 | ```
26 |
27 | **NB** if you have errors alike `Could not open '/var/lib/libvirt/images/terraform_example_root.img': Permission denied'` you need to reconfigure libvirt by setting `security_driver = "none"` in `/etc/libvirt/qemu.conf` and restart libvirt with `sudo systemctl restart libvirtd`.
28 |
29 | Show information about the libvirt/qemu guest:
30 |
31 | ```bash
32 | virsh dumpxml terraform_example
33 | virsh qemu-agent-command terraform_example '{"execute":"guest-info"}' --pretty
34 | virsh qemu-agent-command terraform_example '{"execute":"guest-network-get-interfaces"}' --pretty
35 | ./qemu-agent-guest-exec terraform_example id
36 | ./qemu-agent-guest-exec terraform_example uname -a
37 | ssh-keygen -f ~/.ssh/known_hosts -R "$(terraform output --raw ip)"
38 | ssh "vagrant@$(terraform output --raw ip)"
39 | ```
40 |
41 | Destroy the infrastructure:
42 |
43 | ```bash
44 | time terraform destroy -auto-approve
45 | ```
46 |
47 | List this repository dependencies (and which have newer versions):
48 |
49 | ```bash
50 | GITHUB_COM_TOKEN='YOUR_GITHUB_PERSONAL_TOKEN' ./renovate.sh
51 | ```
52 |
53 | # Virtual BMC
54 |
55 | You can externally control the VM using the following terraform providers:
56 |
57 | * [vbmc terraform provider](https://registry.terraform.io/providers/rgl/vbmc)
58 | * exposes an [IPMI](https://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface) endpoint.
59 | * you can use it with [ipmitool](https://github.com/ipmitool/ipmitool).
60 | * for more information see the [rgl/terraform-provider-vbmc](https://github.com/rgl/terraform-provider-vbmc) repository.
61 | * [sushy-vbmc terraform provider](https://registry.terraform.io/providers/rgl/sushy-vbmc)
62 | * exposes a [Redfish](https://en.wikipedia.org/wiki/Redfish_(specification)) endpoint.
63 | * you can use it with [redfishtool](https://github.com/DMTF/Redfishtool).
64 | * for more information see the [rgl/terraform-provider-sushy-vbmc](https://github.com/rgl/terraform-provider-sushy-vbmc) repository.
65 |
--------------------------------------------------------------------------------
/libvirt-domain.xsl:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | # see https://github.com/hashicorp/terraform
2 | terraform {
3 | required_version = "1.9.2"
4 | required_providers {
5 | # see https://registry.terraform.io/providers/hashicorp/random
6 | # see https://github.com/hashicorp/terraform-provider-random
7 | random = {
8 | source = "hashicorp/random"
9 | version = "3.6.2"
10 | }
11 | # see https://registry.terraform.io/providers/dmacvicar/libvirt
12 | # see https://github.com/dmacvicar/terraform-provider-libvirt
13 | libvirt = {
14 | source = "dmacvicar/libvirt"
15 | version = "0.7.6"
16 | }
17 | }
18 | }
19 |
20 | provider "libvirt" {
21 | uri = "qemu:///system"
22 | }
23 |
24 | variable "prefix" {
25 | type = string
26 | default = "terraform_example"
27 | }
28 |
29 | # see https://github.com/dmacvicar/terraform-provider-libvirt/blob/v0.7.6/website/docs/r/network.markdown
30 | resource "libvirt_network" "example" {
31 | name = var.prefix
32 | mode = "nat"
33 | domain = "example.test"
34 | addresses = ["10.17.3.0/24"]
35 | dhcp {
36 | enabled = false
37 | }
38 | dns {
39 | enabled = true
40 | local_only = false
41 | }
42 | }
43 |
44 | # create a cloud-init cloud-config.
45 | # NB this creates an iso image that will be used by the NoCloud cloud-init datasource.
46 | # see https://github.com/dmacvicar/terraform-provider-libvirt/blob/v0.7.6/website/docs/r/cloudinit.html.markdown
47 | # see journalctl -u cloud-init
48 | # see /run/cloud-init/*.log
49 | # see https://cloudinit.readthedocs.io/en/latest/topics/examples.html#disk-setup
50 | # see https://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html#datasource-nocloud
51 | # see createISO at https://github.com/dmacvicar/terraform-provider-libvirt/blob/v0.7.6/libvirt/cloudinit_def.go#L140-L169
52 | resource "libvirt_cloudinit_disk" "example_cloudinit" {
53 | name = "${var.prefix}_example_cloudinit.iso"
54 | user_data = < 0 ? libvirt_domain.example.network_interface[0].addresses[0] : ""
162 | }
163 |
--------------------------------------------------------------------------------
/qemu-agent-guest-exec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | '''
3 | Execute a command inside the guest.
4 | '''
5 |
6 | import base64
7 | import json
8 | import libvirt
9 | import libvirt_qemu
10 | import logging
11 | import sys
12 | import time
13 |
14 | domain_name = sys.argv[1]
15 | command_path = sys.argv[2]
16 | command_args = sys.argv[3:]
17 |
18 | try:
19 | connection = libvirt.open(None)
20 | except libvirt.libvirtError:
21 | logging.exception('Failed to open connection to the hypervisor')
22 | exit(1)
23 |
24 | try:
25 | domain = connection.lookupByName(domain_name)
26 | except libvirt.libvirtError:
27 | logging.exception(f'Domain {domain_name} is not running')
28 | exit(1)
29 |
30 | # execute a command inside the guest.
31 | # see https://libvirt.org/html/libvirt-libvirt-qemu.html#virDomainQemuAgentCommand
32 | command = json.dumps({
33 | 'execute': 'guest-exec',
34 | 'arguments': {
35 | 'path': command_path,
36 | 'arg': command_args,
37 | 'capture-output': True,
38 | }
39 | })
40 | result = json.loads(libvirt_qemu.qemuAgentCommand(domain, command, -2, 0))
41 | command = json.dumps({
42 | 'execute': 'guest-exec-status',
43 | 'arguments': {
44 | 'pid': result['return']['pid'],
45 | }
46 | })
47 | while True:
48 | result = json.loads(libvirt_qemu.qemuAgentCommand(domain, command, -2, 0))
49 | if result['return']['exited']:
50 | print(base64.b64decode(result['return']['out-data']).decode('utf-8'))
51 | break
52 | time.sleep(0.1)
53 |
--------------------------------------------------------------------------------
/renovate.json5:
--------------------------------------------------------------------------------
1 | // see https://docs.renovatebot.com/templates/
2 | // see https://docs.renovatebot.com/modules/manager/
3 | // see https://docs.renovatebot.com/modules/manager/regex/
4 | // see https://docs.renovatebot.com/configuration-options/
5 | {
6 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
7 | "regexManagers": [
8 | // default datasources.
9 | {
10 | "fileMatch": [
11 | "\\.yml$",
12 | ".sh$",
13 | ],
14 | "matchStrings": [
15 | "# renovate: datasource=(?[^:]+?) depName=(?.+?)( versioning=(?.+?))?( extractVersion=(?.+?))?( registryUrl=(?.+?))?\\s.+?[:=]\\s*[\"']?(?.+?)[\"']?\\s"
16 | ],
17 | "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}",
18 | "extractVersionTemplate": "{{#if extractVersion}}{{{extractVersion}}}{{else}}^v?(?.+)${{/if}}"
19 | },
20 | ]
21 | }
--------------------------------------------------------------------------------
/renovate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 |
4 | # this executes renovate against the local repository.
5 | # NB this uses a temporary gitea instance because running renovate against a
6 | # local directory not (yet?) supported.
7 | # see https://github.com/renovatebot/renovate/issues/3609
8 |
9 | export RENOVATE_USERNAME='renovate'
10 | export RENOVATE_NAME='Renovate Bot'
11 | export RENOVATE_PASSWORD='password'
12 | gitea_container_name="$(basename "$(dirname "$(realpath "${BASH_SOURCE[0]}")")")-renovate-gitea"
13 |
14 | # see https://hub.docker.com/r/gitea/gitea/tags
15 | # renovate: datasource=docker depName=gitea/gitea
16 | gitea_version='1.22.1'
17 |
18 | # see https://hub.docker.com/r/renovate/renovate/tags
19 | # renovate: datasource=docker depName=renovate/renovate extractVersion=(?.+)-slim$
20 | renovate_version='37.431.4'
21 |
22 | # clean.
23 | echo 'Deleting existing Gitea...'
24 | docker rm --force "$gitea_container_name" >/dev/null 2>&1
25 | echo 'Deleting existing temporary files...'
26 | rm -f tmp/renovate-*
27 | install -d tmp
28 |
29 | # start gitea in background.
30 | # see https://docs.gitea.io/en-us/config-cheat-sheet/
31 | # see https://github.com/go-gitea/gitea/releases
32 | # see https://github.com/go-gitea/gitea/blob/v1.22.1/docker/root/etc/s6/gitea/setup
33 | echo 'Starting Gitea...'
34 | docker run \
35 | --detach \
36 | --name "$gitea_container_name" \
37 | -v /etc/timezone:/etc/timezone:ro \
38 | -v /etc/localtime:/etc/localtime:ro \
39 | -e SECRET_KEY=abracadabra \
40 | -p 3000 \
41 | "gitea/gitea:$gitea_version" \
42 | >/dev/null
43 | gitea_addr="$(docker port "$gitea_container_name" 3000 | head -1)"
44 | gitea_url="http://$gitea_addr"
45 | export RENOVATE_ENDPOINT="$gitea_url"
46 | export GIT_PUSH_REPOSITORY="http://$RENOVATE_USERNAME:$RENOVATE_PASSWORD@$gitea_addr/$RENOVATE_USERNAME/test.git"
47 |
48 | # wait for gitea to be ready.
49 | echo "Waiting for Gitea to be ready at $gitea_url..."
50 | GITEA_URL="$gitea_url" bash -euc 'while [ -z "$(wget -qO- "$GITEA_URL/api/v1/version" | jq -r ".version | select(.!=null)")" ]; do sleep 5; done'
51 |
52 | # create user in gitea.
53 | echo "Creating Gitea $RENOVATE_USERNAME user..."
54 | docker exec --user git "$gitea_container_name" gitea admin user create \
55 | --admin \
56 | --email "$RENOVATE_USERNAME@example.com" \
57 | --username "$RENOVATE_USERNAME" \
58 | --password "$RENOVATE_PASSWORD"
59 | curl \
60 | --silent \
61 | --show-error \
62 | --fail-with-body \
63 | -u "$RENOVATE_USERNAME:$RENOVATE_PASSWORD" \
64 | -X 'PATCH' \
65 | -H 'Accept: application/json' \
66 | -H 'Content-Type: application/json' \
67 | -d "{\"full_name\":\"$RENOVATE_NAME\"}" \
68 | "$gitea_url/api/v1/user/settings" \
69 | | jq \
70 | > /dev/null
71 |
72 | # create the user personal access token.
73 | # see https://docs.gitea.io/en-us/api-usage/
74 | # see https://docs.gitea.io/en-us/oauth2-provider/#scopes
75 | # see https://try.gitea.io/api/swagger#/user/userCreateToken
76 | echo "Creating Gitea $RENOVATE_USERNAME user personal access token..."
77 | curl \
78 | --silent \
79 | --show-error \
80 | --fail-with-body \
81 | -u "$RENOVATE_USERNAME:$RENOVATE_PASSWORD" \
82 | -X POST \
83 | -H "Content-Type: application/json" \
84 | -d '{"name": "renovate", "scopes": ["read:user", "write:issue", "write:repository"]}' \
85 | "$gitea_url/api/v1/users/$RENOVATE_USERNAME/tokens" \
86 | | jq -r .sha1 \
87 | >tmp/renovate-gitea-token.txt
88 |
89 | # try the token.
90 | echo "Trying the Gitea $RENOVATE_USERNAME user personal access token..."
91 | RENOVATE_TOKEN="$(cat tmp/renovate-gitea-token.txt)"
92 | export RENOVATE_TOKEN
93 | curl \
94 | --silent \
95 | --show-error \
96 | --fail-with-body \
97 | -H "Authorization: token $RENOVATE_TOKEN" \
98 | -H 'Accept: application/json' \
99 | "$gitea_url/api/v1/version" \
100 | | jq \
101 | > /dev/null
102 |
103 | # create remote repository in gitea.
104 | echo "Creating Gitea $RENOVATE_USERNAME test repository..."
105 | curl \
106 | --silent \
107 | --show-error \
108 | --fail-with-body \
109 | -u "$RENOVATE_USERNAME:$RENOVATE_PASSWORD" \
110 | -X POST \
111 | -H 'Accept: application/json' \
112 | -H 'Content-Type: application/json' \
113 | -d '{"name": "test"}' \
114 | "$gitea_url/api/v1/user/repos" \
115 | | jq \
116 | > /dev/null
117 |
118 | # push the code to local gitea repository.
119 | # NB running renovate locally is not yet supported.
120 | # see https://github.com/renovatebot/renovate/issues/3609
121 | echo "Pushing local repository to Gitea $RENOVATE_USERNAME test repository..."
122 | git push --force "$GIT_PUSH_REPOSITORY"
123 |
124 | # see https://docs.renovatebot.com/modules/platform/gitea/
125 | # see https://docs.renovatebot.com/self-hosted-configuration/#dryrun
126 | # see https://github.com/renovatebot/renovate/blob/main/docs/usage/examples/self-hosting.md
127 | # see https://github.com/renovatebot/renovate/tree/main/lib/modules/datasource
128 | # see https://github.com/renovatebot/renovate/tree/main/lib/modules/versioning
129 | RENOVATE_TOKEN="$(cat tmp/renovate-gitea-token.txt)"
130 | export RENOVATE_TOKEN
131 | # NB these can also be passed as raw positional arguments to docker run.
132 | export RENOVATE_REPOSITORIES="$RENOVATE_USERNAME/test"
133 | # see https://docs.github.com/en/rest/rate-limit#get-rate-limit-status-for-the-authenticated-user
134 | # see https://github.com/settings/tokens
135 | # NB this is only used for authentication. the token should not have any scope enabled.
136 | #export GITHUB_COM_TOKEN='TODO-YOUR-TOKEN'
137 | # let renovate create all the required pull requests.
138 | # see https://docs.renovatebot.com/configuration-options/#prhourlylimit
139 | # see https://docs.renovatebot.com/configuration-options/#prconcurrentlimit
140 | export RENOVATE_PR_HOURLY_LIMIT='0'
141 | export RENOVATE_PR_CONCURRENT_LIMIT='0'
142 | echo 'Running renovate...'
143 | # NB use --dry-run=lookup for not modifying the repository (e.g. for not
144 | # creating pull requests).
145 | docker run \
146 | --rm \
147 | --tty \
148 | --interactive \
149 | --net host \
150 | --env GITHUB_COM_TOKEN \
151 | --env RENOVATE_ENDPOINT \
152 | --env RENOVATE_TOKEN \
153 | --env RENOVATE_REPOSITORIES \
154 | --env RENOVATE_PR_HOURLY_LIMIT \
155 | --env RENOVATE_PR_CONCURRENT_LIMIT \
156 | --env LOG_LEVEL=debug \
157 | --env LOG_FORMAT=json \
158 | "renovate/renovate:$renovate_version-slim" \
159 | --platform=gitea \
160 | --git-url=endpoint \
161 | >tmp/renovate-log.json
162 |
163 | echo 'Getting results...'
164 | # extract the errors.
165 | jq 'select(.err)' tmp/renovate-log.json >tmp/renovate-errors.json
166 | # extract the result from the renovate log.
167 | jq 'select(.msg == "packageFiles with updates") | .config' tmp/renovate-log.json >tmp/renovate-result.json
168 | # extract all the dependencies.
169 | jq 'to_entries[].value[] | {packageFile,dep:.deps[]}' tmp/renovate-result.json >tmp/renovate-dependencies.json
170 | # extract the dependencies that have updates.
171 | jq 'select((.dep.updates | length) > 0)' tmp/renovate-dependencies.json >tmp/renovate-dependencies-updates.json
172 |
173 | # helpers.
174 | function show-title {
175 | echo
176 | echo '#'
177 | echo "# $1"
178 | echo '#'
179 | echo
180 | }
181 |
182 | # show errors.
183 | if [ "$(jq --slurp length tmp/renovate-errors.json)" -ne '0' ]; then
184 | show-title errors
185 | jq . tmp/renovate-errors.json
186 | fi
187 |
188 | # show dependencies.
189 | function show-dependencies {
190 | show-title "$1"
191 | (
192 | printf 'packageFile\tdatasource\tdepName\tcurrentValue\tnewVersions\tskipReason\twarnings\n'
193 | jq \
194 | -r \
195 | '[
196 | .packageFile,
197 | .dep.datasource,
198 | .dep.depName,
199 | .dep.currentValue,
200 | (.dep | select(.updates) | .updates | map(.newVersion) | join(" | ")),
201 | .dep.skipReason,
202 | (.dep | select(.warnings) | .warnings | map(.message) | join(" | "))
203 | ] | @tsv' \
204 | "$2" \
205 | | sort
206 | ) | column -t -s "$(printf \\t)"
207 | }
208 | show-dependencies 'Dependencies' tmp/renovate-dependencies.json
209 | show-dependencies 'Dependencies Updates' tmp/renovate-dependencies-updates.json
210 |
211 | # show the gitea project.
212 | show-title "See PRs at $gitea_url/$RENOVATE_USERNAME/test/pulls (you can login as $RENOVATE_USERNAME:$RENOVATE_PASSWORD)"
213 |
--------------------------------------------------------------------------------