3
3
import argparse
4
4
import os
5
5
import re
6
+ from typing import NamedTuple
7
+
8
+ from bs4 import BeautifulSoup
9
+
10
+ # gfm stands for Github Flavoured Markdown
11
+ from marko .ext .gfm import gfm
12
+
6
13
import requests
7
14
8
15
9
- def get_latest_release () -> (int , int , str ):
10
- gcp_vm_re = re .compile (r'^gcp-gardener_prod-amd64-([0-9]+)\.([0-9]+)-([0-9a-f]+)\.tar\.xz$' )
11
- url = "https://api.github.com/repos/gardenlinux/gardenlinux/releases/latest"
16
+ class GardenVersion (NamedTuple ):
17
+ """
18
+ Type alias for the garden version
19
+ """
20
+ checksum : str
21
+ major : int
22
+ minor : int
23
+ commit : str
24
+
25
+
26
+ def get_latest_release () -> GardenVersion :
27
+ """
28
+ Find the Garden Linux version in a GH release.
29
+
30
+ This method queries the GH API for the latest release of gardenlinux
31
+ and attempts to extract the version for the gcp image from it.
32
+
33
+ The block that holds the image name looks something like this in
34
+ markdown:
35
+ ### Google Cloud Platform (amd64)
36
+ ```
37
+ gcp_image_name: gardenlinux-gcp-8bd7b82716e90c634df25013-1592-9-2eaf0fc6
38
+ ```
39
+
40
+ marko parses the markdown string and translates it to equivalent
41
+ html that looks something like this:
42
+ <h3>Google Cloud Platform (amd64)</h3>
43
+ <pre><code>gcp_image_name: gardenlinux-gcp-8bd7b82716e90c634df25013-1592-9-2eaf0fc6</code></pre>
44
+
45
+ We can then use BeautifulSoup to parse the html and look for the
46
+ data we want. A bit convoluted, but it does not look like we can do
47
+ the same with marko directly.
48
+ """
49
+ gcp_vm_re = re .compile (
50
+ r'^gcp_image_name: gardenlinux-gcp-([0-9a-f]+)-([0-9]+)-([0-9]+)-([0-9a-f]+)$' )
51
+ url = 'https://api.github.com/repos/gardenlinux/gardenlinux/releases/latest'
12
52
headers = {
13
53
'Accept' : 'application/vnd.github+json' ,
14
54
'Authorization' : f'Bearer { os .environ ["GITHUB_TOKEN" ]} ' ,
@@ -18,43 +58,51 @@ def get_latest_release() -> (int, int, str):
18
58
response .raise_for_status ()
19
59
latest_release = response .json ()
20
60
21
- for a in latest_release ['assets' ]:
22
- match = gcp_vm_re .match (a ['name' ])
23
- if match :
24
- major = int (match [1 ])
25
- minor = int (match [2 ])
26
- checksum = match [3 ]
61
+ body = gfm .convert (latest_release ['body' ])
62
+ body = BeautifulSoup (body , features = 'html.parser' )
63
+ h = body .find (name = 'h3' , string = 'Google Cloud Platform (amd64)' )
64
+ if h is None :
65
+ raise RuntimeError ('Failed to find the GCP VM image: Missed <h3>' )
66
+
67
+ pre = h .find_next_sibling ('pre' )
68
+ if pre is None :
69
+ raise RuntimeError ('Failed to find the GCP VM image: Missed <pre>' )
70
+
71
+ match = gcp_vm_re .match (pre .code .string .strip ())
72
+ if match is None :
73
+ raise RuntimeError (
74
+ 'Failed to find the GCP VM image: Version did not match' )
27
75
28
- return ( major , minor , checksum )
29
- raise RuntimeError ( "Failed to find the GCP VM asset" )
76
+ checksum , major , minor , commit = match . groups ( )
77
+ return GardenVersion ( checksum , int ( major ), int ( minor ), commit )
30
78
31
79
32
- def get_current_version (image_file : str ) -> (int , int , str ):
33
- gcp_vm_re = re .compile (r'^gardenlinux-gcp-gardener-prod-amd64-([0-9]+)-([0-9]+)-([0-9a-f]+)$' )
80
+ def get_current_version (image_file : str ) -> GardenVersion :
81
+ gcp_vm_re = re .compile (
82
+ r'^gardenlinux-gcp-([-0-9a-z]+)-([0-9]+)-([0-9]+)-([0-9a-f]+)$' )
34
83
35
84
with open (image_file , 'r' ) as f :
36
85
image = f .readline ()
37
86
match = gcp_vm_re .match (image )
38
87
if match is None :
39
88
raise RuntimeError ('Configured image did not match' )
40
89
41
- major = int (match [1 ])
42
- minor = int (match [2 ])
43
- checksum = match [3 ]
90
+ checksum = match [1 ]
91
+ major = int (match [2 ])
92
+ minor = int (match [3 ])
93
+ commit = match [4 ]
44
94
45
- return ( major , minor , checksum )
95
+ return GardenVersion ( checksum , major , minor , commit )
46
96
47
97
48
- def get_gardenlinux_image (version_data : (int , int , str )) -> str :
49
- major = version_data [0 ]
50
- minor = version_data [1 ]
51
- checksum = version_data [2 ]
98
+ def get_gardenlinux_image (version_data : GardenVersion ) -> str :
99
+ checksum , major , minor , commit = version_data
52
100
53
- return f'gardenlinux-gcp-gardener-prod-amd64- { major } -{ minor } -{ checksum } '
101
+ return f'gardenlinux-gcp-{ checksum } - { major } -{ minor } -{ commit } '
54
102
55
103
56
- def image_is_outdated (latest : ( int , int , str ), current : ( int , int , str ) ) -> bool :
57
- return latest [: 2 ] > current [: 2 ]
104
+ def image_is_outdated (latest : GardenVersion , current : GardenVersion ) -> bool :
105
+ return latest [1 : 3 ] > current [1 : 3 ]
58
106
59
107
60
108
def main (image_file : str ):
0 commit comments