Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote Cache OpenAPI specification doesn't mention x-artifact-tag for /v8/artifacts/{hash} get API #9217

Open
1 task done
trivikr opened this issue Oct 3, 2024 · 0 comments
Labels
area: docs Improvements or additions to documentation

Comments

@trivikr
Copy link
Contributor

trivikr commented Oct 3, 2024

Verify canary release

  • I verified that the issue exists in the latest Turborepo canary release.

Link to code that reproduces this issue

N/A, this is an issue with Remote Cache OpenAPI

What package manager are you using / does the bug impact?

npm

What operating system are you using?

Mac

Which canary version will you have in your reproduction?

2.1.2-canary.1

Describe the Bug

Remote Cache OpenAPI specification doesn't mention x-artifact-tag for /v8/artifacts/{hash} get API.

The existing OpenAPI specification doesn't seem to be versioned in URL, so I'm copying the contents here for v3.0.3.

put

Contains x-artifact-tag in header

{
        "description": "Uploads a cache artifact identified by the `hash` specified on the path. The cache artifact can then be downloaded with the provided `hash`.",
        "operationId": "uploadArtifact",
        "security": [
          {
            "bearerToken": []
          }
        ],
        "summary": "Upload a cache artifact",
        "tags": ["artifacts"],
        "responses": {
          "202": {
            "description": "File successfully uploaded",
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "urls": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array",
                      "description": "Array of URLs where the artifact was updated",
                      "example": [
                        "https://api.vercel.com/v2/now/artifact/12HKQaOmR5t5Uy6vdcQsNIiZgHGB"
                      ]
                    }
                  },
                  "required": ["urls"],
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "One of the provided values in the request query is invalid.\nOne of the provided values in the headers is invalid\nFile size is not valid"
          },
          "401": {
            "description": ""
          },
          "402": {
            "description": "The account was soft-blocked for an unhandled reason.\nThe account is missing a payment so payment method must be updated"
          },
          "403": {
            "description": "The customer has reached their spend cap limit and has been paused. An owner can disable the cap or raise the limit in settings.\nThe Remote Caching usage limit has been reached for this account for this billing cycle.\nRemote Caching has been disabled for this team or user. An owner can enable it in the billing settings.\nYou do not have permission to access this resource."
          }
        },
        "parameters": [
          {
            "in": "header",
            "description": "The artifact size in bytes",
            "required": true,
            "schema": {
              "description": "The artifact size in bytes",
              "type": "number"
            },
            "name": "Content-Length"
          },
          {
            "in": "header",
            "description": "The time taken to generate the uploaded artifact in milliseconds.",
            "required": false,
            "schema": {
              "type": "number",
              "description": "The time taken to generate the uploaded artifact in milliseconds.",
              "example": 400
            },
            "name": "x-artifact-duration"
          },
          {
            "in": "header",
            "description": "The continuous integration or delivery environment where this artifact was generated.",
            "required": false,
            "schema": {
              "type": "string",
              "description": "The continuous integration or delivery environment where this artifact was generated.",
              "example": "VERCEL",
              "maxLength": 50
            },
            "name": "x-artifact-client-ci"
          },
          {
            "in": "header",
            "description": "1 if the client is an interactive shell. Otherwise 0",
            "required": false,
            "schema": {
              "type": "integer",
              "description": "1 if the client is an interactive shell. Otherwise 0",
              "example": 0,
              "minimum": 0,
              "maximum": 1
            },
            "name": "x-artifact-client-interactive"
          },
          {
            "in": "header",
            "description": "The base64 encoded tag for this artifact. The value is sent back to clients when the artifact is downloaded as the header `x-artifact-tag`",
            "required": false,
            "schema": {
              "type": "string",
              "description": "The base64 encoded tag for this artifact. The value is sent back to clients when the artifact is downloaded as the header `x-artifact-tag`",
              "example": "Tc0BmHvJYMIYJ62/zx87YqO0Flxk+5Ovip25NY825CQ=",
              "maxLength": 600
            },
            "name": "x-artifact-tag"
          },
          {
            "name": "hash",
            "description": "The artifact hash",
            "in": "path",
            "required": true,
            "schema": {
              "example": "12HKQaOmR5t5Uy6vdcQsNIiZgHGB",
              "description": "The artifact hash",
              "type": "string"
            }
          },
          {
            "description": "The Team identifier to perform the request on behalf of.",
            "in": "query",
            "name": "teamId",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The Team slug to perform the request on behalf of.",
            "in": "query",
            "name": "slug",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        }
      }

get

Does not contain x-artifact-tag in header

{
        "description": "Downloads a cache artifact indentified by its `hash` specified on the request path. The artifact is downloaded as an octet-stream. The client should verify the content-length header and response body.",
        "operationId": "downloadArtifact",
        "security": [
          {
            "bearerToken": []
          }
        ],
        "summary": "Download a cache artifact",
        "tags": ["artifacts"],
        "responses": {
          "200": {
            "description": "The artifact was found and is downloaded as a stream. Content-Length should be verified.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "An octet stream response that will be piped to the response stream."
                }
              }
            }
          },
          "400": {
            "description": "One of the provided values in the request query is invalid.\nOne of the provided values in the headers is invalid"
          },
          "401": {
            "description": ""
          },
          "402": {
            "description": "The account was soft-blocked for an unhandled reason.\nThe account is missing a payment so payment method must be updated"
          },
          "403": {
            "description": "The customer has reached their spend cap limit and has been paused. An owner can disable the cap or raise the limit in settings.\nThe Remote Caching usage limit has been reached for this account for this billing cycle.\nRemote Caching has been disabled for this team or user. An owner can enable it in the billing settings.\nYou do not have permission to access this resource."
          },
          "404": {
            "description": "The artifact was not found"
          }
        },
        "parameters": [
          {
            "in": "header",
            "description": "The continuous integration or delivery environment where this artifact is downloaded.",
            "schema": {
              "type": "string",
              "description": "The continuous integration or delivery environment where this artifact is downloaded.",
              "example": "VERCEL",
              "maxLength": 50
            },
            "name": "x-artifact-client-ci"
          },
          {
            "in": "header",
            "description": "1 if the client is an interactive shell. Otherwise 0",
            "schema": {
              "type": "integer",
              "description": "1 if the client is an interactive shell. Otherwise 0",
              "example": 0,
              "minimum": 0,
              "maximum": 1
            },
            "name": "x-artifact-client-interactive"
          },
          {
            "name": "hash",
            "description": "The artifact hash",
            "in": "path",
            "required": true,
            "schema": {
              "example": "12HKQaOmR5t5Uy6vdcQsNIiZgHGB",
              "description": "The artifact hash",
              "type": "string"
            }
          },
          {
            "description": "The Team identifier to perform the request on behalf of.",
            "in": "query",
            "name": "teamId",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The Team slug to perform the request on behalf of.",
            "in": "query",
            "name": "slug",
            "schema": {
              "type": "string"
            }
          }
        ]
      }

As per documentation in Artifact Integrity and Authenticity Verification, it appears that get call needs to have x-artifact-tag in header for turborepo client to process it.

Turborepo will verify the Remote Cache artifacts' integrity and authenticity when they're downloaded. Any artifacts that fail to verify will be ignored and treated as a cache miss by Turborepo.

The client source code checks for signature in x-artifact-tag

let body = if let Some(signer_verifier) = &self.signer_verifier {
let expected_tag = response
.headers()
.get("x-artifact-tag")
.ok_or(CacheError::ArtifactTagMissing(Backtrace::capture()))?;

Expected Behavior

The Remote Cache OpenAPI specification should mention x-artifact-tag for /v8/artifacts/{hash} get API

To Reproduce

Go through Remote Cache API specification, documentation and client implementation in description

Additional context

No response

@trivikr trivikr added kind: bug Something isn't working needs: triage New issues get this label. Remove it after triage labels Oct 3, 2024
@chris-olszewski chris-olszewski added area: docs Improvements or additions to documentation and removed kind: bug Something isn't working needs: triage New issues get this label. Remove it after triage labels Oct 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: docs Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants