Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package openSUSE-release-tools for 
openSUSE:Factory checked in at 2025-10-08 18:16:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openSUSE-release-tools (Old)
 and      /work/SRC/openSUSE:Factory/.openSUSE-release-tools.new.11973 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openSUSE-release-tools"

Wed Oct  8 18:16:02 2025 rev:540 rq:1309772 version:20251001.0ed4bc8b

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/openSUSE-release-tools/openSUSE-release-tools.changes
    2025-09-11 16:40:46.234877669 +0200
+++ 
/work/SRC/openSUSE:Factory/.openSUSE-release-tools.new.11973/openSUSE-release-tools.changes
 2025-10-08 18:20:21.105087755 +0200
@@ -1,0 +2,35 @@
+Wed Oct 01 08:58:57 UTC 2025 - [email protected]
+
+- Update to version 20251001.0ed4bc8b:
+  * container_cleaner.py: Use _result?view=binarylist
+  * container_cleaner.py: Make use of defaultdict
+
+-------------------------------------------------------------------
+Tue Sep 30 08:04:41 UTC 2025 - [email protected]
+
+- Update to version 20250930.617a0826:
+  * gocd: Add SLES 16.1 pipelines.
+
+-------------------------------------------------------------------
+Mon Sep 29 13:04:45 UTC 2025 - [email protected]
+
+- Update to version 20250929.6c5cb012:
+  * dashboard: look for 'templates' independly of working directory
+
+-------------------------------------------------------------------
+Mon Sep 29 11:59:52 UTC 2025 - [email protected]
+
+- Update to version 20250929.8ef1733d:
+  * dashboard: full color in openQA stats
+  * dashboard: move Leap logic to the python script
+  * dashboard: remove dead code
+  * dashboard: use jinja2 templates directly
+
+-------------------------------------------------------------------
+Mon Sep 22 13:38:09 UTC 2025 - [email protected]
+
+- Update to version 20250922.c808382c:
+  * container_cleaner.py: Warn about and ignore sources without binaries
+  * container_cleaner.py: Don't bother checking the "local" arch
+
+-------------------------------------------------------------------

Old:
----
  openSUSE-release-tools-20250904.5c7b6442.obscpio

New:
----
  openSUSE-release-tools-20251001.0ed4bc8b.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ openSUSE-release-tools.spec ++++++
--- /var/tmp/diff_new_pack.PiqQ0f/_old  2025-10-08 18:20:21.877120154 +0200
+++ /var/tmp/diff_new_pack.PiqQ0f/_new  2025-10-08 18:20:21.881120321 +0200
@@ -21,7 +21,7 @@
 %define announcer_filename factory-package-news
 %define services osrt-slsa.target [email protected] 
[email protected] [email protected] [email protected]
 Name:           openSUSE-release-tools
-Version:        20250904.5c7b6442
+Version:        20251001.0ed4bc8b
 Release:        0
 Summary:        Tools to aid in staging and release work for openSUSE/SUSE
 License:        GPL-2.0-or-later AND MIT

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.PiqQ0f/_old  2025-10-08 18:20:21.929122336 +0200
+++ /var/tmp/diff_new_pack.PiqQ0f/_new  2025-10-08 18:20:21.937122672 +0200
@@ -1,7 +1,7 @@
 <servicedata>
   <service name="tar_scm">
     <param 
name="url">https://github.com/openSUSE/openSUSE-release-tools.git</param>
-    <param 
name="changesrevision">5c7b6442fb1233ada3fc1bb83167209f5086dc94</param>
+    <param 
name="changesrevision">0ed4bc8bcafea4303ea5d5fef6d960d3e3f95155</param>
   </service>
 </servicedata>
 

++++++ openSUSE-release-tools-20250904.5c7b6442.obscpio -> 
openSUSE-release-tools-20251001.0ed4bc8b.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20250904.5c7b6442/container_cleaner.py 
new/openSUSE-release-tools-20251001.0ed4bc8b/container_cleaner.py
--- old/openSUSE-release-tools-20250904.5c7b6442/container_cleaner.py   
2025-09-04 15:24:16.000000000 +0200
+++ new/openSUSE-release-tools-20251001.0ed4bc8b/container_cleaner.py   
2025-10-01 10:58:08.000000000 +0200
@@ -1,5 +1,5 @@
 #!/usr/bin/python3
-# (c) 2019 [email protected]
+# (c) 2025 [email protected]
 # GPLv3-only
 
 import osc.conf
@@ -8,6 +8,7 @@
 import ToolBase
 import sys
 import re
+from collections import defaultdict
 from lxml import etree as xml
 
 
@@ -21,18 +22,17 @@
         directory = xml.parse(self.retried_GET(url))
         return directory.xpath("entry/@name")
 
-    def getDirBinaries(self, path):
-        url = self.makeurl(path)
-        directory = xml.parse(self.retried_GET(url))
-        return directory.xpath("binary/@filename")
+    def getBinaryList(self, project):
+        url = self.makeurl(["build", project, "_result"], query={"view": 
"binarylist"})
+        return xml.parse(self.retried_GET(url))
 
     def findSourcepkgsToDelete(self, project):
         # Get a list of all images
         srccontainers = self.getDirEntries(["source", project])
 
-        # Sort them into buckets for each package:
+        # Sort the released packages into buckets for each origin package:
         # {"opensuse-tumbleweed-image": 
["opensuse-tumbleweed-image.20190402134201", ...]}
-        buckets = {}
+        buckets = defaultdict(list)
         regex_maintenance_release = re.compile(R"^(.+)\.[0-9]+$")
         for srccontainer in srccontainers:
             # Get the right bucket
@@ -44,10 +44,8 @@
                 # Not renamed
                 package = srccontainer
 
-            if package not in buckets:
-                buckets[package] = []
-
-            buckets[package] += [srccontainer]
+            if srccontainer not in buckets[package]:
+                buckets[package] += [srccontainer]
 
         for package in buckets:
             # Sort each bucket: Newest provider first
@@ -57,15 +55,17 @@
         # Get a hash for sourcecontainer -> arch with binaries
         # {"opensuse-tumbleweed-image.20190309164844": ["aarch64", "armv7l", 
"armv6l"],
         # "kubic-pause-image.20190306124139": ["x86_64", "i586"], ... }
-        srccontainerarchs = {}
+        srccontainerarchs = defaultdict(list)
+
+        resultlist = self.getBinaryList(project)
 
-        archs = self.getDirEntries(["build", project, "containers"])
         regex_srccontainer = re.compile(R"^([^:]+)(:[^:]+)?$")
-        for arch in archs:
-            buildcontainers = self.getDirEntries(["build", project, 
"containers", arch])
-            for buildcontainer in buildcontainers:
-                bins = self.getDirBinaries(["build", project, "containers", 
arch, buildcontainer])
-                if len(bins) > 0:
+        for arch_result in resultlist.xpath("result"):
+            arch = arch_result.get("arch")
+
+            for binarylist in arch_result.xpath("binarylist"):
+                buildcontainer = binarylist.get("package")
+                if len(binarylist.xpath("binary")) > 0:
                     match = regex_srccontainer.match(buildcontainer)
                     if not match:
                         raise Exception(f"Could not map {buildcontainer} to 
source container")
@@ -74,9 +74,6 @@
                     if srccontainer not in srccontainers:
                         raise Exception(f"Mapped {buildcontainer} to wrong 
source container ({srccontainer})")
 
-                    if srccontainer not in srccontainerarchs:
-                        srccontainerarchs[srccontainer] = []
-
                     logging.debug("%s provides binaries for %s", srccontainer, 
arch)
                     srccontainerarchs[srccontainer] += [arch]
 
@@ -84,19 +81,18 @@
         can_delete = []
         for package in buckets:
             # {"x86_64": 1, "aarch64": 2, ...}
-            archs_found = {}
-            for arch in archs:
-                archs_found[arch] = 0
+            archs_found = defaultdict(lambda: 0)
 
             for srccontainer in buckets[package]:
                 contributes = False
-                if srccontainer in srccontainerarchs:
-                    for arch in srccontainerarchs[srccontainer]:
-                        if archs_found[arch] < 5:
-                            archs_found[arch] += 1
-                            contributes = True
-
-                if contributes:
+                for arch in srccontainerarchs[srccontainer]:
+                    if archs_found[arch] < 5:
+                        archs_found[arch] += 1
+                        contributes = True
+
+                if len(srccontainerarchs[srccontainer]) == 0:
+                    logging.warning("%s has no binaries (any flavor/any arch) 
- skipping", srccontainer)
+                elif contributes:
                     logging.debug("%s contributes to %s", srccontainer, 
package)
                 else:
                     logging.info("%s does not contribute", srccontainer)
@@ -105,7 +101,7 @@
                         # A and B aren't deleted because they have newer 
sources. This is
                         # to avoid deleting something due to unforeseen 
circumstances, e.g.
                         # OBS didn't copy the binaries yet.
-                        logging.info("No newer provider found either, 
ignoring")
+                        logging.warning("No newer provider found either, 
ignoring")
                     else:
                         can_delete += [srccontainer]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20250904.5c7b6442/dashboard/generate.py 
new/openSUSE-release-tools-20251001.0ed4bc8b/dashboard/generate.py
--- old/openSUSE-release-tools-20250904.5c7b6442/dashboard/generate.py  
2025-09-04 15:24:16.000000000 +0200
+++ new/openSUSE-release-tools-20251001.0ed4bc8b/dashboard/generate.py  
2025-10-01 10:58:08.000000000 +0200
@@ -1,9 +1,9 @@
 #!/usr/bin/python3
 
 import argparse
-import logging
 import osc
 import yaml
+import os
 from osc.core import http_GET, makeurl, show_project_meta
 from osclib.core import attribute_value_load
 from lxml import etree as ET
@@ -11,7 +11,7 @@
 from urllib.error import HTTPError
 from datetime import datetime, timezone
 
-from flask import Flask, render_template
+from jinja2 import Environment, FileSystemLoader
 
 
 class Fetcher(object):
@@ -122,16 +122,13 @@
     def build_summary(self, repo):
         return fetcher.build_summary(self.name, repo)
 
-    def all_archs(self):
-        self.all_archs
-
     def openqa_summary(self):
         return self.fetcher.openqa_results(self.openqa_id, 
self.ttm_status.get('testing'))
 
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser(
-        description='Bot to sync openQA status to OBS')
+        description='Generate static dashboard of openSUSE status')
     parser.add_argument("--apiurl", '-A', type=str, help='API URL of OBS')
     parser.add_argument('-p', '--project', type=str, default='Factory',
                         help='openSUSE version to make the check (Factory, 
15.2)')
@@ -145,9 +142,6 @@
     apiurl = osc.conf.config['apiurl']
 
     fetcher = Fetcher(apiurl, args)
-    logging.basicConfig(level=logging.INFO)
-
-    app = Flask(__name__)
 
     if ("Factory" in args.project):
         fetcher.add('openSUSE:Factory', nick='Factory', 
download_url='https://download.opensuse.org/tumbleweed/iso/',
@@ -177,9 +171,15 @@
         fetcher.add('openSUSE:Leap:15.6:Images', nick='Leap:15.6:Images', 
openqa_group='openSUSE Leap 15.6 Images',
                     openqa_version='15.6', openqa_groupid=117)
 
-    with app.app_context():
-        rendered = render_template('dashboard.html',
-                                   projectname=args.project,
-                                   lastupdate=datetime.now(timezone.utc),
-                                   projects=fetcher.projects)
-        print(rendered)
+    is_leap = not fetcher.projects[0].name.startswith("openSUSE:Factory")
+
+    # Get the path from where the script is run and look for templates in the 
same directory
+    script_dir = os.path.dirname(os.path.abspath(__file__))
+    template_dir = os.path.join(script_dir, 'templates')
+    env = Environment(loader=FileSystemLoader(template_dir), autoescape=True)
+    template = env.get_template('dashboard.html')
+    rendered = template.render(projectname=args.project,
+                               lastupdate=datetime.now(timezone.utc),
+                               projects=fetcher.projects,
+                               is_leap=is_leap)
+    print(rendered)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20250904.5c7b6442/dashboard/templates/dashboard.html 
new/openSUSE-release-tools-20251001.0ed4bc8b/dashboard/templates/dashboard.html
--- 
old/openSUSE-release-tools-20250904.5c7b6442/dashboard/templates/dashboard.html 
    2025-09-04 15:24:16.000000000 +0200
+++ 
new/openSUSE-release-tools-20251001.0ed4bc8b/dashboard/templates/dashboard.html 
    2025-10-01 10:58:08.000000000 +0200
@@ -1,8 +1,3 @@
-{% if "Factory" in projects[0].name %}
-{% set is_leap = False %}
-{% else %}
-{% set is_leap = True %}
-{% endif%}
 <!doctype html>
 <html lang="en">
 
@@ -108,8 +103,10 @@
         </td>
         <td>
         {% set openqa_summary = project.openqa_summary() %}
-        {% for state in openqa_summary.keys() %}
-          <span class="openqa{{ state }}">{{ state }}</span>: {{ 
openqa_summary[state]|length }}
+        {% for state, count in openqa_summary.items() %}
+          <span class="openqa{{ state }}">
+            {{ state }}: {{ count|length }}
+          </span>
         {% endfor %}
         </td>
       </tr>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20250904.5c7b6442/gocd/sles.target.gocd.yaml 
new/openSUSE-release-tools-20251001.0ed4bc8b/gocd/sles.target.gocd.yaml
--- old/openSUSE-release-tools-20250904.5c7b6442/gocd/sles.target.gocd.yaml     
2025-09-04 15:24:16.000000000 +0200
+++ new/openSUSE-release-tools-20251001.0ed4bc8b/gocd/sles.target.gocd.yaml     
2025-10-01 10:58:08.000000000 +0200
@@ -1,5 +1,104 @@
 format_version: 3
 pipelines:
+  SLES16.1.Images:
+    group: SLES
+    lock_behavior: unlockWhenFinished
+    materials:
+      repos:
+        git: git://botmaster.suse.de/suse-repos.git
+        auto_update: true
+        whitelist:
+          - SUSE:SLFO:Products:SLES:16.1_-_images.yaml
+        destination: repos
+      scripts:
+        auto_update: true
+        git: https://github.com/openSUSE/openSUSE-release-tools.git
+        whitelist:
+          - DO_NOT_TRIGGER
+        destination: scripts
+    environment_variables:
+      OSC_CONFIG: /home/go/config/oscrc-staging-bot
+    stages:
+    - Expect.Images.To.Finish:
+        resources:
+        - staging-bot
+        tasks:
+        - script: |
+            export PYTHONPATH=scripts
+            ./scripts/gocd/verify-repo-built-successful.py -A 
https://api.suse.de -p SUSE:SLFO:Products:SLES:16.1 -r images
+
+    - Release.Images.To.Test:
+        approval: manual
+        roles:
+        - SLE
+        environment_variables:
+          OSC_CONFIG: /home/go/config/oscrc-totest-manager
+        resources:
+        - staging-bot
+        tasks:
+        - script: |-
+            set -e
+            for image in agama-installer-SLES kiwi-templates-Minimal; do
+              osc -A https://api.suse.de release 
--target-project=SUSE:SLFO:Products:SLES:16.1:TEST --target-repository=images 
-r images SUSE:SLFO:Products:SLES:16.1 $image
+            done
+            osc -A https://api.suse.de release  
--target-project=SUSE:SLFO:Products:SLES:16.1:TEST --target-repository=product 
-r product SUSE:SLFO:Products:SLES:16.1 000productcompose
+            sleep 600
+            while (osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:TEST/_result?view=summary&repository=product"
 | grep "result project" | grep -v 'code="published" state="published">'); do
+                echo PENDING
+                sleep 600
+            done
+            osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:TEST/_result?view=summary&repository=product"
 | grep "result project" | grep 'code="published" state="published">' && echo 
PUBLISHED
+            while (osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:TEST/_result?view=summary&repository=images"
 | grep "result project" | grep -v 'code="published" state="published">'); do
+                echo PENDING
+                sleep 600
+            done
+            osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:TEST/_result?view=summary&repository=images"
 | grep "result project" | grep 'code="published" state="published">' && echo 
PUBLISHED
+
+  SLES16.1.Images.To.Publish:
+    group: SLES
+    materials:
+      repos:
+        git: git://botmaster.suse.de/suse-repos.git
+        auto_update: true
+        whitelist:
+          - SUSE:SLFO:Products:SLES:16.1_-_images.yaml
+        destination: repos
+      scripts:
+        auto_update: true
+        git: https://github.com/openSUSE/openSUSE-release-tools.git
+        whitelist:
+          - DO_NOT_TRIGGER
+        destination: scripts
+    environment_variables:
+      OSC_CONFIG: /home/go/config/oscrc-staging-bot
+    stages:
+    - Release.Images:
+        approval: manual
+        roles:
+        - SLE
+        environment_variables:
+          OSC_CONFIG: /home/go/config/oscrc-totest-manager
+        resources:
+        - staging-bot
+        tasks:
+        - script: |-
+            set -e
+            for image in agama-installer-SLES kiwi-templates-Minimal; do
+              osc -A https://api.suse.de release 
--target-project=SUSE:SLFO:Products:SLES:16.1:PUBLISH 
--target-repository=images -r images SUSE:SLFO:Products:SLES:16.1:TEST $image
+            done
+            osc -A https://api.suse.de release  
--target-project=SUSE:SLFO:Products:SLES:16.1:PUBLISH 
--target-repository=product -r product SUSE:SLFO:Products:SLES:16.1:TEST 
000productcompose
+            sleep 600
+            while (osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:PUBLISH/_result?view=summary&repository=product"
 | grep "result project" | grep -v 'code="published" state="published">'); do
+                echo PENDING
+                sleep 600
+            done
+            osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:PUBLISH/_result?view=summary&repository=product"
 | grep "result project" | grep 'code="published" state="published">' && echo 
PUBLISHED
+            while (osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:PUBLISH/_result?view=summary&repository=images"
 | grep "result project" | grep -v 'code="published" state="published">'); do
+                echo PENDING
+                sleep 600
+            done
+            osc -A https://api.suse.de/ api 
"/build/SUSE:SLFO:Products:SLES:16.1:PUBLISH/_result?view=summary&repository=images"
 | grep "result project" | grep 'code="published" state="published">' && echo 
PUBLISHED
+
   SLES16.0.Images:
     group: SLES
     lock_behavior: unlockWhenFinished
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20250904.5c7b6442/tests/container_cleaner_tests.py 
new/openSUSE-release-tools-20251001.0ed4bc8b/tests/container_cleaner_tests.py
--- 
old/openSUSE-release-tools-20250904.5c7b6442/tests/container_cleaner_tests.py   
    2025-09-04 15:24:16.000000000 +0200
+++ 
new/openSUSE-release-tools-20251001.0ed4bc8b/tests/container_cleaner_tests.py   
    2025-10-01 10:58:08.000000000 +0200
@@ -1,6 +1,7 @@
 import unittest
 
 from container_cleaner import ContainerCleaner
+from lxml import etree as xml
 
 
 class MockedContainerCleaner(ContainerCleaner):
@@ -9,35 +10,34 @@
 
     def getDirEntries(self, path):
         """Mock certain OBS APIs returning directory entries"""
-        if path == ["source", "mock:prj"]:
-            srccontainers = [a.split(":")[0] for a in 
self.container_arch_map.keys()]
-            return list(set(srccontainers))  # Remove duplicates
-        elif path == ["build", "mock:prj", "containers"]:
-            all_archs = []
-            for archs in self.container_arch_map.values():
-                all_archs += archs
-
-            return list(set(all_archs))
-        elif path[0:3] == ["build", "mock:prj", "containers"] and len(path) == 
4:
-            ret = []
-            for srccontainer in self.container_arch_map:
-                ret += [srccontainer]
-
-            return ret
-        else:
-            raise RuntimeError(f"Path {path} not expected")
+        assert path == ["source", "mock:prj"]
+        srccontainers = [a.split(":")[0] for a in 
self.container_arch_map.keys()]
+        return list(set(srccontainers))  # Remove duplicates
 
-    def getDirBinaries(self, path):
+    def getBinaryList(self, project):
         """Mock certain OBS APIs returning a list of binaries"""
-        if path[0:3] == ["build", "mock:prj", "containers"] and len(path) == 5:
-            arch = path[3]
-            srccontainer = path[4]
-            if arch in self.container_arch_map[srccontainer]:
-                return ["A binary"]
-
-            return []
-        else:
-            raise RuntimeError(f"Path {path} not expected")
+        assert project == "mock:prj"
+
+        resultlist = xml.fromstring('<resultlist 
state="6b99f3a517302521e047e4100dc32384"/>')
+        all_archs = set()
+        for archs in self.container_arch_map.values():
+            all_archs |= set(archs)
+
+        for arch in set(sum(self.container_arch_map.values(), [])):
+            result = xml.fromstring('<result repository="containers" 
code="published" state="published"/>')
+            result.set("project", project)
+            result.set("arch", arch)
+
+            for buildcontainer in self.container_arch_map:
+                binarylist = xml.Element("binarylist", attrib={"package": 
buildcontainer})
+                if arch in self.container_arch_map[buildcontainer]:
+                    binarylist.append(xml.fromstring('<binary filename="A 
binary"/>'))
+
+                result.append(binarylist)
+
+            resultlist.append(result)
+
+        return xml.ElementTree(element=resultlist)
 
 
 class TestContainerCleaner(unittest.TestCase):
@@ -94,7 +94,7 @@
                               "e.56": ["i586"],
                               "e.57": ["i586"]}
 
-        to_be_deleted_exp = ["c", "c.01", "c.02", "c.03", "c.04",
+        to_be_deleted_exp = ["c", "c.01", "c.02", "c.04",
                              "e.51"]
 
         return self.doTest(container_arch_map, to_be_deleted_exp)
@@ -123,7 +123,7 @@
                               "e.56": ["i586"],
                               "e.57": ["i586"]}
 
-        to_be_deleted_exp = ["c", "c.01", "c.02", "c.03", "c.04",
+        to_be_deleted_exp = ["c", "c.01", "c.02", "c.04",
                              "e.51"]
 
         return self.doTest(container_arch_map, to_be_deleted_exp)

++++++ openSUSE-release-tools.obsinfo ++++++
--- /var/tmp/diff_new_pack.PiqQ0f/_old  2025-10-08 18:20:28.073380183 +0200
+++ /var/tmp/diff_new_pack.PiqQ0f/_new  2025-10-08 18:20:28.105381526 +0200
@@ -1,5 +1,5 @@
 name: openSUSE-release-tools
-version: 20250904.5c7b6442
-mtime: 1756992256
-commit: 5c7b6442fb1233ada3fc1bb83167209f5086dc94
+version: 20251001.0ed4bc8b
+mtime: 1759309088
+commit: 0ed4bc8bcafea4303ea5d5fef6d960d3e3f95155
 

Reply via email to