generateCacheMemoryArtifactUpload generates artifact upload steps for cache-memory. This should be called after agent execution steps to ensure cache is uploaded after the agent has finished. pinAction resolves the upload-artifact action reference; pass c.getActionPin from Compiler methods.
(builder *strings.Builder, data *WorkflowData, pinAction func(string) string)
| 715 | // This should be called after agent execution steps to ensure cache is uploaded after the agent has finished. |
| 716 | // pinAction resolves the upload-artifact action reference; pass c.getActionPin from Compiler methods. |
| 717 | func generateCacheMemoryArtifactUpload(builder *strings.Builder, data *WorkflowData, pinAction func(string) string) { |
| 718 | if data.CacheMemoryConfig == nil || len(data.CacheMemoryConfig.Caches) == 0 { |
| 719 | return |
| 720 | } |
| 721 | |
| 722 | // Only upload artifacts when threat detection is enabled (needed for update_cache_memory job) |
| 723 | // When threat detection is disabled, cache is saved automatically by actions/cache post-action |
| 724 | threatDetectionEnabled := IsDetectionJobEnabled(data.SafeOutputs) |
| 725 | if !threatDetectionEnabled { |
| 726 | cacheLog.Print("Skipping cache-memory artifact upload (threat detection disabled)") |
| 727 | return |
| 728 | } |
| 729 | |
| 730 | cacheLog.Printf("Generating cache-memory artifact upload steps for %d caches", len(data.CacheMemoryConfig.Caches)) |
| 731 | |
| 732 | // Use backward-compatible paths only when there's a single cache with ID "default" |
| 733 | useBackwardCompatiblePaths := len(data.CacheMemoryConfig.Caches) == 1 && data.CacheMemoryConfig.Caches[0].ID == "default" |
| 734 | |
| 735 | // In workflow_call context, apply the per-invocation prefix to avoid artifact name clashes. |
| 736 | prefix := artifactPrefixExprForDownstreamJob(data) |
| 737 | |
| 738 | for _, cache := range data.CacheMemoryConfig.Caches { |
| 739 | // Skip restore-only caches |
| 740 | if cache.RestoreOnly { |
| 741 | continue |
| 742 | } |
| 743 | |
| 744 | cacheDir := cacheMemoryDirFor(cache.ID) |
| 745 | |
| 746 | // Add a best-effort git integrity check and reseed step before upload. |
| 747 | // This prevents upload-artifact from failing on torn/corrupt .git object stores. |
| 748 | if useBackwardCompatiblePaths { |
| 749 | builder.WriteString(" - name: Check cache-memory git integrity\n") |
| 750 | } else { |
| 751 | fmt.Fprintf(builder, " - name: Check cache-memory git integrity (%s)\n", cache.ID) |
| 752 | } |
| 753 | builder.WriteString(" if: always()\n") |
| 754 | builder.WriteString(" continue-on-error: true\n") |
| 755 | builder.WriteString(" env:\n") |
| 756 | fmt.Fprintf(builder, " GH_AW_CACHE_DIR: %s\n", cacheDir) |
| 757 | builder.WriteString(" run: bash \"${RUNNER_TEMP}/gh-aw/actions/check_cache_memory_git_integrity.sh\"\n") |
| 758 | |
| 759 | // Add upload-artifact step for each cache (runs always) |
| 760 | if useBackwardCompatiblePaths { |
| 761 | builder.WriteString(" - name: Upload cache-memory data as artifact\n") |
| 762 | } else { |
| 763 | fmt.Fprintf(builder, " - name: Upload cache-memory data as artifact (%s)\n", cache.ID) |
| 764 | } |
| 765 | fmt.Fprintf(builder, " uses: %s\n", pinAction("actions/upload-artifact")) |
| 766 | builder.WriteString(" if: always()\n") |
| 767 | builder.WriteString(" with:\n") |
| 768 | // Always use the new artifact name and path format, with prefix in workflow_call context |
| 769 | if useBackwardCompatiblePaths { |
| 770 | fmt.Fprintf(builder, " name: %scache-memory\n", prefix) |
| 771 | } else { |
| 772 | fmt.Fprintf(builder, " name: %scache-memory-%s\n", prefix, cache.ID) |
| 773 | } |
| 774 | builder.WriteString(" include-hidden-files: true\n") |