No access to build artifacts in Xcode Cloud

Lost access to all the build artifacts in Xcode Cloud.

When I try downloading any build artifact from the web page I'm getting:

{"message":"You are not authorized to access this team’s resources."}

Same attempt from Xcode just crashes the app. Started to happen today or some time yesterday, after 12am EST.

Answered by DTS Engineer in 814785022

@beetee , @Manulpz , and @sergiy_s_idv

The issue is resolved. Please try again.

Encountering the same issues here. First time using XCode Cloud yesterday, not a great first experience.

Thought I'd share my solution here for anyone experiencing the same issues and have experience with Python. I made some simple scripts that can be used to manually extract out the download URLs of each artifact.

# generate_token.py
import jwt
import time
from datetime import datetime, timedelta

# Define your App Store Connect API credentials
KEY_ID = '________'
ISSUER_ID = '________'
PRIVATE_KEY_PATH = '________.p8'

with open(PRIVATE_KEY_PATH, 'r') as key_file:
    private_key = key_file.read()

def generate_token():
    headers = {
        "alg": "ES256",
        "kid": KEY_ID,
        "typ": "JWT"
    }
    payload = {
        "iss": ISSUER_ID,
        "exp": int(time.time()) + 20 * 60,  # Token expiration in 20 minutes
        "aud": "appstoreconnect-v1"
    }
    token = jwt.encode(payload, private_key, algorithm="ES256", headers=headers)
    return token
# fetch_workflows.py
import time
import requests
from datetime import datetime, timedelta

def fetch_products(token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciProducts"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])
  
def fetch_workflows(product_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciProducts/{product_id}/workflows"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    from generate_token import generate_token
    products = fetch_products(generate_token())
    print(f"Found {len(products)} products")
    for product in products:
        print(f"{product['attributes']['name']} ({product['attributes']['productType']}): {product['id']}")

        workflows = fetch_workflows(product['id'], generate_token())
        print(f"Found {len(workflows)} workflows")
        for workflow in workflows:
            print(f"{workflow['attributes']['name']}: {workflow['id']}")
# fetch_build_runs.py
import time
import requests
from datetime import datetime, timedelta

# Fetch all build runs for the specified workflow
def fetch_build_runs(workflow_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciWorkflows/{workflow_id}/buildRuns"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    params = {
        "limit": 200  # Adjust the limit as needed; 200 is the maximum
    }
    
    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    import argparse
    from generate_token import generate_token
    parser = argparse.ArgumentParser(description="Fetch all build runs for a given workflow ID.")
    parser.add_argument("workflow_id", help="The workflow ID for which to fetch build runs for.")
    args = parser.parse_args()

    build_runs = fetch_build_runs(args.workflow_id, generate_token())
    print(f"Found {len(build_runs)} runs for workflow {args.workflow_id}")
    for build_run in build_runs:
        print(f"Build {build_run['attributes']['number']}: {build_run['id']}")
# fetch_build_actions.py
import time
import requests
from datetime import datetime, timedelta

def fetch_build_actions(build_run_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciBuildRuns/{build_run_id}/actions"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    import argparse
    from generate_token import generate_token
    parser = argparse.ArgumentParser(description="Fetch all build actions for a given build run ID.")
    parser.add_argument("build_run_id", help="The build run ID for which to fetch build actions from")
    args = parser.parse_args()

    build_actions = fetch_build_actions(args.build_run_id, generate_token())
    print(f"Found {len(build_actions)} actions for run {args.build_run_id}")
    for build_action in build_actions:
        print(f"{build_action['attributes']['name']}: {build_action['id']}")
# fetch_artifacts.py
import time
import requests
from datetime import datetime, timedelta

def fetch_artifacts(build_action_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciBuildActions/{build_action_id}/artifacts"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    import argparse
    from generate_token import generate_token
    parser = argparse.ArgumentParser(description="Fetch all artifacts for a given build action ID.")
    parser.add_argument("build_action_id", help="The build action ID for which to fetch artifacts.")
    args = parser.parse_args()

    artifacts = fetch_artifacts(args.build_action_id, generate_token())
    print(f"Found {len(artifacts)} artifacts for action {args.build_action_id}")
    for artifact in artifacts:
        print(f"{artifact['attributes']['fileName']}: {artifact['attributes']['downloadUrl']}")

Note that you will need to pip install cryptography pyjwt requests.

Same here. I just tried today. I had access to artifacts last week but not today.

We are looking into the issue. Thank you for your patience.

Accepted Answer

@beetee , @Manulpz , and @sergiy_s_idv

The issue is resolved. Please try again.

No access to build artifacts in Xcode Cloud
 
 
Q