{"id":30139594,"url":"https://github.com/irgaly/xcode-cache","last_synced_at":"2025-08-11T02:15:52.186Z","repository":{"id":194026775,"uuid":"689926284","full_name":"irgaly/xcode-cache","owner":"irgaly","description":"A GitHub Action to store Xcode's Build Cache for incremental build on CI","archived":false,"fork":false,"pushed_at":"2025-07-18T11:36:45.000Z","size":10367,"stargazers_count":55,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-18T15:37:48.602Z","etag":null,"topics":["github-actions","ios","xcode"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/irgaly.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"irgaly","custom":["https://github.com/irgaly/irgaly"]}},"created_at":"2023-09-11T07:40:27.000Z","updated_at":"2025-07-18T11:36:47.000Z","dependencies_parsed_at":"2023-11-15T13:29:38.496Z","dependency_job_id":"8352dbca-0a4b-4970-972b-9e5de3519379","html_url":"https://github.com/irgaly/xcode-cache","commit_stats":null,"previous_names":["irgaly/xcode-cache"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/irgaly/xcode-cache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fxcode-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fxcode-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fxcode-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fxcode-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/irgaly","download_url":"https://codeload.github.com/irgaly/xcode-cache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fxcode-cache/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265809676,"owners_count":23831938,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github-actions","ios","xcode"],"created_at":"2025-08-11T02:15:32.953Z","updated_at":"2025-08-11T02:15:52.178Z","avatar_url":"https://github.com/irgaly.png","language":"TypeScript","funding_links":["https://github.com/sponsors/irgaly","https://github.com/irgaly/irgaly"],"categories":[],"sub_categories":[],"readme":"# xcode-cache\n\nA GitHub Action to store Xcode's Build Cache for incremental build on CI.\n\n* This action caches:\n    * `DerivedData`\n        * That contains Xcode's Build Cache.\n    * `SourcePackages`\n        * That contains SwiftPM cloned repositories.\n    * Your source code's `modified time` (mtime)\n\n# Usage\n\nUse this action in GitHub Actions workflow.\n\n```yaml\n    - uses: actions/checkout@v4\n      ...\n    - uses: irgaly/xcode-cache@v1\n      with:\n        key: xcode-cache-deriveddata-${{ github.workflow }}-${{ github.sha }}\n        restore-keys: xcode-cache-deriveddata-${{ github.workflow }}-\n      ...\n    - name: (Your build step)\n      run: |\n        fastlane ...\n```\n\nXcode's DerivedData is used for incremental build, so it's recommended to use `github.sha` in cache\nkey.\n\n# Configuration examples\n\n## Custom DerivedData and SourcePackages locations\n\n```yaml\n    - uses: irgaly/xcode-cache@v1\n      with:\n        key: xcode-cache-deriveddata-${{ github.workflow }}-${{ github.sha }}\n        restore-keys: xcode-cache-deriveddata-${{ github.workflow }}-\n        deriveddata-directory: DerivedData\n        sourcepackages-directory: SourcePackages\n      ...\n```\n\n## Store all project file's mtime attributes\n\n```yaml\n    - uses: irgaly/xcode-cache@v1\n      with:\n        key: xcode-cache-deriveddata-${{ github.workflow }}-${{ github.sha }}\n        restore-keys: xcode-cache-deriveddata-${{ github.workflow }}-\n        restore-mtime-targets: |\n          YourApp/**/*\n      ...\n```\n\n## Use custom cache key for SourcePackages cache\n\nThe cache key of SourcePackages is default\nto `irgaly/xcode-cache-sourcepackages-${{ hashFiles('.../Package.resolved') }}`.\nYou can specify your custom key.\n\n```yaml\n    - uses: irgaly/xcode-cache@v1\n      with:\n        key: xcode-cache-deriveddata-${{ github.workflow }}-${{ github.sha }}\n        restore-keys: xcode-cache-deriveddata-${{ github.workflow }}-\n        swiftpm-cache-key: your-soucepackages-${{ hashFiles('your/path/to/Package.resolved') }}\n        swiftpm-cache-restore-keys: |\n          your-custom-restore-keys-here-...\n      ...\n```\n\n# Platform\n\nThis action is for only macOS runner.\n\n# Caching details\n\nThis action caches below entries.\n\n## DerivedData\n\nThe DerivedData directory has all of intermediates build output files such as compiled objects.\n\nA DerivedData directory that is default to `~/Library/Developer/Xcode/DerivedData` or specified\nby `deriveddata-directory` input.\n\nThis directory will be cached with nanosecond resolution mtime\nby [@actions/cache](https://github.com/actions/toolkit/).\n\n## SourcePackages\n\nThe SourcePackages directory has clones of SwiftPM if you used SwiftPM dependencies with Xcode.\n\nA SourcePackages directory that is default\nto `~/Library/Developer/Xcode/DerivedData/{App name}-{ID}/SourcePackages` or specified\nby `sourcepackages-directory` input.\n\nThis directory will be cached with nanosecond resolution mtime\nby [@actions/cache](https://github.com/actions/toolkit/).\n\n## Source Code's mtime attributes\n\nXcode stores build input file's mtime information with **nanosecond resolution** to DerivedData.\nSo, on CI environment, it's required to restore all input file's mtime from previous build after\ncheckout sources.\n\nThis action will store input file's mtime attributes and their SHA-256 hash\nto `(DerivedData directory)/xcode-cache-mtime.json`.\n\nThen this action will restore their mtime attributes if their SHA-256 are same after checkout\nsources.\n\nFor example, `xcode-cache-mtime.json`'s contents will be:\n\n```json\n[\n  {\n    \"path\": \"sample/MyApp/MyApp/ContentView.swift\",\n    \"time\": \"1694751978.570357000\",\n    \"sha256\": \"a1a6707fc09625c0a5f49c3b8127da42358085506bbe2246469f00c0a7a2276b\"\n  },\n  {\n    \"path\": \"sample/MyApp/MyApp/MyAppApp.swift\",\n    \"time\": \"1694751978.543212000\",\n    \"sha256\": \"0b97d516fc64a2ec833b9eefe769d658947c66cc528ada637ac916da7b87f5bc\"\n  },\n  ...\n]\n```\n\n### Default target file's to store mtime attributes\n\nIf `use-default-mtime-targets` is set to true (default),\nthis action will store these file's mtime attributes:\n\n* `**/*.swift`\n* `**/*.xib`\n* `**/*.storyboard`\n* `**/*.strings`\n* `**/*.xcstrings`\n* `**/*.plist`\n* `**/*.intentdefinition`\n* `**/*.json`\n* `**/*.xcassets`\n* `**/*.xcassets/**/*`\n* `**/*.bundle`\n* `**/*.bundle/**/*`\n* `**/*.xcdatamodel`\n* `**/*.xcdatamodel/**/*`\n* `**/*.framework`,\n* `**/*.framework/**/*`,\n* `**/*.xcframework`,\n* `**/*.xcframework/**/*`,\n* `**/*.m`\n* `**/*.mm`\n* `**/*.h`\n* `**/*.c`\n* `**/*.cc`\n* `**/*.cpp`\n* `**/*.hpp`\n* `**/*.hxx`\n\nYou can add any target by glob pattern with `restore-mtime-targets` input.\n\n# Delete old incremental build cache when job succeeded\n\nIf `delete-used-deriveddata-cache: true` is configured, xcode-cache will delete old DerivedData\ncache from GitHub Actions Cache Storage.\nThis will help you to manage your repository's Cache Storage space.\n\nThis operation will use GitHub Actions API for deleting cache.\n**Be sure `actions: write` has granted to your token.**\n\n* [REST API | GitHub Actions Cache](https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-github-actions-caches-for-a-repository-using-a-cache-key)\n* [GitHub Actions | Assigning permissions to jobs](https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs)\n\nPlease see the official document of GitHub Actions Cache management for more details.\n\n* [GitHub Docs | Caching dependencies to speed up workflows | Force deleting cache entries](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries)\n\n# All Options\n\n```yaml\n    - uses: irgaly/xcode-cache@v1\n      with:\n        # Cache key for DerivedData cache\n        #\n        # required\n        key: { your derived data key }\n\n        # Restore keys for DerivedData cache\n        #\n        # optional, multiline\n        # dofault: empty\n        restore-keys: |\n          {your derived data restore keys}\n\n        # DerivedData directory path\n        #\n        # optional\n        # default: ~/Library/Developer/Xcode/DerivedData\n        deriveddata-directory: { your DerivedData directory path }\n\n        # SourcePackages directory path\n        #\n        # optional, multiline\n        # default: {DerivedDirectory path}/SourcePackages\n        sourcepackages-directory: { your SourcePackages directory path }\n\n        # Target file glob patterns to store mtime attributes\n        # This glob pattern is applied with GitHub Actions toolkit glob option implicitDescendants = false\n        #\n        # optional, multiline\n        # default: empty\n        restore-mtime-targets: |\n          your/target/**/*\n\n        # Xcode's Package.resolved file path glob patterns\n        # Package.resolved file is used for swiftpm-cache-key if it is not specified\n        #\n        # optional, multiline\n        # default:\n        #   **/*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved\n        #   **/*.xcworkspace/xcshareddata/swiftpm/Package.resolved\n        swiftpm-package-resolved-file: |\n          YourApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved\n\n        # Cache key for SourcePackages\n        #\n        # optional\n        # default: irgaly/xcode-cache-sourcepackages-${{ hashFiles( {swiftpm-package-resolved-file} ) }}'\n        swiftpm-cache-key: { your SourcePackages cache key }\n\n        # Cache restore keys for SourcePackages\n        #\n        # optional\n        # default: empty\n        swiftpm-cache-restore-keys:\n\n        # Use default target file glob patterns to store mtime attributes\n        #\n        # optional\n        # default: true\n        use-default-mtime-targets: true\n\n        # Delete the DerivedData cache that used for this build,\n        # only when this job has succeeded, the cache has hit from `restore-keys` and\n        # the Cache belongs to same branch from this job.\n        #\n        # actions: write permission is required for your token to use this feature.\n        #\n        # Cache will be deleted by GitHub Actions API\n        # https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-github-actions-caches-for-a-repository-using-a-cache-key\n        #\n        # optional\n        # default: false\n        delete-used-deriveddata-cache: false\n\n        # The GitHub Token for deleting DerivedData cache\n        # This is used to access GitHub Actions Cache API\n        #\n        # optional\n        # default: ${{ github.token }}\n        token: ${{ github.token }}\n\n        # More detailed logging\n        #\n        # optional\n        # default: false\n        verbose: false\n\n        # Cache read-only mode\n        # If true, the action will only read from the cache and not write to it\n        #\n        # optional\n        # default: false\n        cache-read-only: false\n```\n\n# Outputs\n\nThis action\nprovides\nsome [step outputs](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter).\n\nFor example, you can use these values by `${{ steps.{step id}.outputs.restored }}`\n\n| key                    | value                                                                                                                        |\n|------------------------|------------------------------------------------------------------------------------------------------------------------------|\n| `restored`             | `true`: DerivedData restored from cache (includes restore-keys hit) / `false`: DerivedData cache not hit                     |\n| `restored-key`         | The key of DerivedData cache hit. This will not set when cache has not hit.                                                  |\n| `swiftpm-restored`     | `true`: SourcePackages restored from cache (includes swiftpm-cache-restore-keys hit) / `false`: SourcePackages cache not hit |\n| `swiftpm-restored-key` | The key of SourcePackages cache hit. This will not set when cache has not hit.                                               |\n\n# Appendix\n\n## Ruby one-liner for restoring mtimes\n\nThis is a ruby one-liner for restoring mtimes from `xcode-cache-mtime.json`.\nYou may use this one-liner if you'd like to restore at any time you want in GitHub Actions workflow\nstep.\n\n```shell\n% ruby -rjson -rdigest -rbigdecimal -e 'JSON.parse(STDIN.read).each{|i|f=i[\"path\"];t=BigDecimal(i[\"time\"]);File.utime(t,t,f)if(File.exist?(f)\u0026\u0026(File.directory?(f)?Digest::SHA256.new.yield_self{|s|Dir.children(f).sort.each{s.update(_1)};s.hexdigest}:Digest::SHA256.file(f).hexdigest)==i[\"sha256\"])}' \u003c DerivedData/xcode-cache-mtime.json\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firgaly%2Fxcode-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Firgaly%2Fxcode-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firgaly%2Fxcode-cache/lists"}