Skip to content

Allow published_at as sort option for repository details

Adie (she/her) requested to merge 351031-allow-sorting-published-at into master

What does this MR do and why?

Issue: Sort the container registry tags list by publis... (#351031)

The container registry API recently added published_at as a possible sorting option. API docs here.

In this MR, we would like to extend the GraphQL client to also receive sorting by published_at ascending / -published_at descending as an option. We also update the method map_sort_field to accept sort options that have multiple underscore (_) (i.e. published_at_asc in addition to name_desc).

From the API docs, we see that:

For pagination purposes, when used in conjunction with the last and before query parameters, the values must be base64 encoded with the following format base64(TIMESTAMP|TAG_NAME), where TIMESTAMP is a string in ISO 8061 format with microsecond precision, followed by the separator character | and finishing with the tag name. For example, for the timestamp 2023-02-01T00:00:01.000000Z and tag name latest, the encoded value will be MjAyMy0wMi0wMVQwMDowMDowMS4wMDAwMDBafGxhdGVzdAo=

This is already handled by our parse_pagination_cursor method which just fetches the URI provided for the previous and next pages by the API via the Link header as documented here. We will see this below when we validate it locally

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

How to set up and validate locally

Prerequisites:

A. The Gitlab API client is available on migrated container repositories, so GitLab.com for now. To simulate this, we can go to app/models/container_repository.rb and add a || true:

def migrated?
  Gitlab.com_except_jh? || true
end

B. Make sure also that you have the container registry running and that the Gitlab API is supported.

ContainerRegistry::GitlabApiClient.supports_gitlab_api?
#=> true

C. We will be working with pagination, so it would be helpful to have a lot of tags in the container registry 🙌

Steps

  1. Go to the GraphQL explorer locally: http://gdk.test:3000/-/graphql-explorer
  2. Add in the following query. The following query, fetches tags in pages of 5 tags each with the sorting set to PUBLISHED_AT_DESC. We also fetch the pageInfo, so we can the last and before parameters.
query {
  containerRepository(id: "gid://gitlab/ContainerRepository/16") {
    id
    tags(first: 5, sort: PUBLISHED_AT_DESC) {
      nodes {
        name
        publishedAt
      }
      pageInfo {
        endCursor
        startCursor
        hasNextPage
        hasPreviousPage
      }
    }
  }
}

Locally, I got the following results. You probably have different values depending on your tags.

{
  "data": {
    "containerRepository": {
      "id": "gid://gitlab/ContainerRepository/16",
      "tags": {
        "nodes": [
          {
            "name": "mm",
            "publishedAt": "2024-05-01T06:04:55+00:00"
          },
          {
            "name": "ll",
            "publishedAt": "2024-05-01T06:04:53+00:00"
          },
          {
            "name": "kk",
            "publishedAt": "2024-05-01T06:04:51+00:00"
          },
          {
            "name": "jj",
            "publishedAt": "2024-05-01T06:04:49+00:00"
          },
          {
            "name": "ii",
            "publishedAt": "2024-05-01T06:04:46+00:00"
          }
        ],
        "pageInfo": {
          "endCursor": "MjAyNC0wNS0wMVQwNjowNDo0Ni45NzUzMzJafGlp",
          "startCursor": null,
          "hasNextPage": true,
          "hasPreviousPage": false
        }
      }
    }
  }
}

We can see that the pagination returned the endCursor MjAyNC0wNS0wMVQwNjowNDo0Ni45NzUzMzJafGlp. You probably have a different value here. Note that this is only present if there is still a next page to this query. Copy the value that you have in endCursor. We then update the main query to include this endCursor so we get the second page.

Update query fetching page 2:

query {
  containerRepository(id: "gid://gitlab/ContainerRepository/16") {
    id
    tags(first: 5, sort: PUBLISHED_AT_DESC, after:"MjAyNC0wNS0wMVQwNjowNDo0Ni45NzUzMzJafGlp") {
      nodes {
        name
        publishedAt
      }
      pageInfo {
        endCursor
        startCursor
        hasNextPage
        hasPreviousPage
      }
    }
  }
}

With this, I get the following result locally:

{
  "data": {
    "containerRepository": {
      "id": "gid://gitlab/ContainerRepository/16",
      "tags": {
        "nodes": [
          {
            "name": "hh",
            "publishedAt": "2024-05-01T06:04:44+00:00"
          },
          {
            "name": "gg",
            "publishedAt": "2024-05-01T06:04:14+00:00"
          },
          {
            "name": "ff",
            "publishedAt": "2024-05-01T06:04:12+00:00"
          },
          {
            "name": "ee",
            "publishedAt": "2024-05-01T06:04:09+00:00"
          },
          {
            "name": "dd",
            "publishedAt": "2024-05-01T06:04:05+00:00"
          }
        ],
        "pageInfo": {
          "endCursor": "MjAyNC0wNS0wMVQwNjowNDowNS4wNzM5NjZafGRk",
          "startCursor": "MjAyNC0wNS0wMVQwNjowNDo0NC43NzE0NDhafGho",
          "hasNextPage": true,
          "hasPreviousPage": true
        }
      }
    }
  }
}

Feel free to try out different sorting options: NAME_ASC, NAME_DESC, PUBLISHED_AT_ASC and PUBLISHED_AT_DESC.

Related to #351031

Edited by Adie (she/her)

Merge request reports