Skip to content

Repository files navigation

GitHub Profile API

Spring Boot service for the Branch platform take-home exercise. It exposes GET /users/{username}, retrieves public GitHub user and repository data, and returns the merged JSON shape requested in docs/Platform_Coding_Exercise.txt.

TLDR

  • Run locally with ./mvnw spring-boot:run, or build a container with docker build -t github-profile-api ..
  • Test with ./mvnw verify; the build runs the automated suite and enforces 100% line and branch coverage for reported packages.
  • Implementation is a single Java 21 / Spring Boot service with controller, service, client, domain, and config layers.
  • GitHub calls are live at runtime, while tests use stubbed GitHub responses for repeatability.
  • Successful lookups are cached briefly with Caffeine; repository pagination uses per_page=100 with a configurable max page cap.
  • No service-level auth is implemented because the assignment uses public GitHub data; optional X-GitHub-Token passthrough can improve GitHub rate limits and public field availability.

Requirements

  • Java 21
  • Maven Wrapper is included; no separate Maven install is required for ./mvnw commands
  • Network access to api.github.com for live manual calls

Run

./mvnw spring-boot:run

The service starts on port 8080.

Docker

Build and run the service in a container:

docker build -t github-profile-api .
docker run --rm -p 8080:8080 github-profile-api

Then call the API from the host:

curl -i http://localhost:8080/users/octocat

Runtime settings can be overridden with Spring Boot environment variables, for example:

docker run --rm -p 8080:8080 \
  -e GITHUB_API_TIMEOUT=2s \
  -e GITHUB_CACHE_TTL=10m \
  github-profile-api

API Contract

The public API contract is documented in docs/openapi.yml. The Spec Kit design copy is kept at specs/001-github-profile-api/contracts/openapi.yaml.

Use

curl -i http://localhost:8080/users/octocat

Example response shape:

{
  "user_name": "octocat",
  "display_name": "The Octocat",
  "avatar": "https://avatars.githubusercontent.com/u/583231?v=4",
  "geo_location": "San Francisco",
  "email": null,
  "url": "https://api.github.com/users/octocat",
  "created_at": "Tue, 25 Jan 2011 18:44:36 GMT",
  "repos": [
    {
      "name": "boysenberry-repo-1",
      "url": "https://api.github.com/repos/octocat/boysenberry-repo-1"
    }
  ]
}

Optional GitHub token passthrough:

curl -i -H "X-GitHub-Token: $GITHUB_TOKEN" http://localhost:8080/users/octocat

The token is forwarded to GitHub as Authorization: Bearer ... for that request only. It is not service-level authentication and is not logged or stored. Authenticated GitHub requests can improve rate limits and may allow GitHub to return public profile fields such as email when available.

Validation example:

curl -i http://localhost:8080/users/-

Expected status: 400 with code INVALID_USERNAME.

Missing user example:

curl -i http://localhost:8080/users/this-user-should-not-exist-branch-demo

Expected status: 404 with code PROFILE_NOT_FOUND.

Test

./mvnw clean compile
./mvnw test
./mvnw verify

The automated suite uses stubbed GitHub HTTP responses, so tests do not depend on live GitHub availability or rate limits.

Coverage is generated by JaCoCo during verify, and the build enforces 100% line and branch coverage for each reported package:

./mvnw verify

Open target/site/jacoco/index.html for the HTML report, or inspect target/site/jacoco/jacoco.csv for a machine-readable summary. Spring Boot bootstrap code and the defensive SHA-256-unavailable cache-key branch are excluded from the coverage gate.

Architecture

The service is intentionally a single Spring Boot application because the assignment asks for one endpoint and fast evaluator setup. The code is still separated into enterprise-style layers:

  • controller: HTTP contract and sanitized error responses
  • service: validation, orchestration, mapping, and cache use
  • client: GitHub HTTP integration and upstream error translation
  • domain: client-facing immutable response records
  • config: outbound HTTP and cache configuration

The controller delegates to the service. The service validates usernames, checks the cache, calls the GitHub client for user and repository data, maps the result, and caches successful lookups. The GitHub client owns external URL paths, repository pagination, response parsing, timeout handling, and upstream status translation.

Authentication

No service-level authentication or authorization layer is implemented. The assignment requires access to public GitHub data and does not require clients to authenticate to this service.

Clients may optionally send X-GitHub-Token with a GitHub token. The service forwards that value only to GitHub as a bearer token for the current lookup. This is upstream GitHub authentication passthrough, not authentication to this service. Tokens are not logged, stored, or included in error responses.

Error Handling

Client-facing failures use stable error codes:

  • INVALID_USERNAME
  • PROFILE_NOT_FOUND
  • UPSTREAM_RATE_LIMITED
  • UPSTREAM_TIMEOUT
  • UPSTREAM_UNAVAILABLE
  • INTERNAL_ERROR

Error responses are intentionally sanitized. They do not expose stack traces, Java class names, secrets, or raw upstream response bodies.

Caching

Successful profile summaries are cached in memory for a short period using Caffeine. This reduces repeated GitHub calls during an evaluation session and helps avoid avoidable rate-limit pressure. Failed lookups are not cached in the initial implementation.

Cache entries are partitioned by authentication context. Unauthenticated lookups use a public username cache key. Requests with X-GitHub-Token use a SHA-256 fingerprint of the token plus the username, so authenticated and unauthenticated responses do not share cache entries and raw tokens are never stored in cache keys.

Configuration defaults live in src/main/resources/application.yml:

  • github.api.base-url
  • github.api.timeout
  • github.api.max-repository-pages
  • github.cache.ttl

Implementation Phases

Phase 1, functional baseline:

  • Maven/Spring project setup
  • GitHub user and repository retrieval
  • Required response mapping
  • Success-path endpoint and tests

Phase 2, reliability and defensive behavior:

  • Username validation
  • Not-found, rate-limit, timeout, and upstream failure handling
  • Sanitized error contract tests

Phase 3, enterprise readiness:

  • Short-lived caching
  • Health endpoint exposure
  • README and quickstart documentation
  • Full compile, test, and verify checks

Tradeoffs

  • No database is included because durable persistence is not required for the exercise.
  • Live GitHub calls are used at runtime, but tests use HTTP stubs for repeatability.
  • Repository retrieval follows GitHub pagination with per_page=100 and a configurable maximum page count to avoid unbounded upstream calls during unauthenticated evaluation. Very large GitHub accounts may therefore return a bounded subset of repositories unless github.api.max-repository-pages is increased.

About

Spring Boot REST API that aggregates GitHub profile and repository data for the Branch platform take-home.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages