Skip to content

Alpine package version #11591

Open
Open

Description

@mike632t

📋 Description

Badges for the latest package versions for debian arch and fedora exist, can you add a badge for the latest alpine package (both main and community)?

Thank you.

🔗 Data

You can query the packages using
https://pkgs.alpinelinux.org/packages?name=<package_name>

Or retrieve the package details directly from the APKINDEX file

#!/usr/bin/env python3
#
#  Get Alpine Package Details
#
#  Downloads  and parses the APKINDEX file from the Alpine Linux repository
#  and extracts the metadata for any matching package(s).
#
#  Copyright(C) 2025 - MT
#
#  This  program is free software: you can redistribute it and/or modify it
#  under  the terms of the GNU General Public License as published  by  the
#  Free  Software Foundation, either version 3 of the License, or (at  your
#  option) any later version.
#
#  This  program  is distributed in the hope that it will  be  useful,  but
#  WITHOUT   ANY   WARRANTY;   without even   the   implied   warranty   of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
#  Public License for more details.
#
#  You  should have received a copy of the GNU General Public License along
#  with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#  24 Dec 25  0.1.0001  - Initial version - MT
#

import io, sys, os, json, tarfile
from urllib import request
from fnmatch import fnmatch

def get_alpine_package_details(pattern, repository="main", release="latest-stable", arch="x86_64"):  # Sensible defaults...
   url = "https://dl-cdn.alpinelinux.org/alpine/" + release + "/" + repository + "/" + arch + "/APKINDEX.tar.gz"  # URL for package information
   try:
      resp = request.urlopen(url, timeout=15)  # Fetch the tar.gz achive from Alpine mirror (with timeout)
      data = resp.read()
   except Exception as error:
      raise RuntimeError("Failed to fetch URL " + url + "\n" + str(error))
      # return [{"error": "Failed to fetch URL", "url": url, "reason": str(error)}]  # Return error as JSON
   try:
      with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as archive:  # Open the tar.gz archive in memory
         index = archive.extractfile("APKINDEX")  # Extract package index file
         if index is None:  # File not found in archive
            raise RuntimeError("APKINDEX not found in archive")  # Throw an error
            # return [{"error": "APKINDEX not found in archive"}]  # Return error as JSON
         data = index.read().decode("utf-8", "ignore")  # Read contents of package index
   except Exception as error:
      raise RuntimeError("Failed to parse APKINDEX "+ str(error))  # Throw an error
      # return [{"error": "Failed to parse APKINDEX", "reason": str(error)}]  # Return error as JSON
   results = []  # Details of all matching packages
   pkg = {}  # Dictionary to hold current package details
   found = False
   for line in data.splitlines():  # Parse package details line by line
      if line.startswith("P:"):  # It is a package name
         if found:  # If we already found a package, append it to the results before starting the next
            results.append(pkg)
            pkg = {}
            found = False
         name = line[2:].strip()  # Extract package name
         if fnmatch(name, pattern):  # Check if the package name matches the pattern
            found = True
            pkg["name"] = name
      elif found and line.startswith("V:"):  # Package version
         pkg["version"] = "v" + line[2:].strip().split("-", 1)[0]  # Ignore anything after a '-'
      elif found and line.startswith("T:"):  # Package text (description)
         pkg["description"] = line[2:].strip()
      elif found and line.startswith("L:"):  # Package licence
         pkg["license"] = line[2:].strip()
      elif found and line.startswith("U:"):  # Package URL
         pkg["url"] = line[2:].strip()
      elif not line.strip() and found:
         results.append(pkg)  # End of package detals append it to results
         pkg = {}
         found = False
   if found and pkg:  # Append the last package (if file ends without a blank line)
      results.append(pkg)
   return results

if __name__ == "__main__":
   if len(sys.argv) < 2:  # Require at least one argument
      sys.exit("Usage: " + os.path.basename(sys.argv[0]) + " <package> [repository] [release] [archecture]")
   try:
      pkg = get_alpine_package_details(*sys.argv[1:])  # Expand all command-line arguments and pass to get_alpine_package_details()
      sys.stderr.write(json.dumps(pkg, indent=2) + "\n")  # Print results as JSON
   except Exception as error:
      # raise error
      sys.stderr.write("Error: " + str(error) + "\n")

🎤 Motivation

Provides a shield to track alpine releases. I'd expect this to be used alongside the corresponding debian, fedora and arch sheilds...

Activity

  1. PyvesB commented on Dec 24, 2025

    @PyvesB
    Member

    Hello @mike632t 👋🏻

    Thanks for the suggestion, sounds reasonable. Would you like to contribute the badge? We've got a nice tutorial to get you started. 😉

  2. mike632t commented on Dec 24, 2025

    @mike632t
    Author

    Maybe (I really don't need another project right now but...) are there any examples that I could use to work out how to parse the HTML returned by the URL as this returns an HTML page not JSON..

    https://pkgs.alpinelinux.org/packages?name=<package_name>
    
  3. PyvesB commented on Dec 24, 2025

    @PyvesB
    Member

    Ah, sorry, I had not realised this was HTML-only. Is there no JSON/XML API at all?

  4. mike632t commented on Dec 24, 2025

    @mike632t
    Author

    Unfortunately, I don't know if there is.

  5. PyvesB commented on Dec 24, 2025

    @PyvesB
    Member

    That's unfortunate. We don't currently accept badges that scrap HTML webpages (see guideline here), we'd need to request a proper upstream API before we could go ahead with this.

  6. mike632t commented on Dec 25, 2025

    @mike632t
    Author

    Probably a bit too cheeky but there are a couple of 'third party' services that do provide an API.

    https://repology.org/api/v1/project/<package-name>
    
    https://release-monitoring.org/api/v2/packages/?name=<package-name>&distribution=Alpine  
    
  7. PyvesB commented on Dec 26, 2025

    @PyvesB
    Member

    We do have a open issue for a Repology version badge: #929. It probably wouldn't be a bad idea to leverage that to get information for Alpine and other distributions.

  8. heliocarlitos commented on Feb 15, 2026

    @heliocarlitos
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-upstream-helpNot actionable without help from a service providerservice-badgeNew or updated service badge

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions