diff --git a/README.md b/README.md index f8695ec..a717aa0 100644 --- a/README.md +++ b/README.md @@ -261,6 +261,56 @@ Each platform entry recognizes the following properties: * `hash` must be one of `"blake3"` or `"sha256"`, but it defaults to `"blake3"`, so it is optional. +## Action Inputs + +This action supports the following inputs: + +* `config` (required): Path to .json file in the repo that defines how DotSlash files should be generated. +* `tag` (required): Tag identifying the release whose assets should be used. +* `include-build-metadata` (optional): Whether to include build metadata in the generated DotSlash files. Defaults to `true`. + +## Build Metadata + +By default, the action embeds build metadata in the generated DotSlash files to provide traceability about how and when the files were generated. This metadata includes: + +* **Source configuration**: Path to the config file used to generate the DotSlash file +* **CI information**: Repository, commit SHA, run ID, workflow name, actor, and event type +* **Generation timestamp**: When the DotSlash file was generated +* **CI job URL**: Direct link to the GitHub Actions run that generated the file + +Example of embedded metadata: + +```json +{ + "name": "my-tool", + "platforms": { ... }, + "build_metadata": { + "source_config": ".github/workflows/dotslash-config.json", + "ci": { + "github_repository": "owner/repo", + "github_sha": "abc123def456", + "github_run_id": "987654321", + "github_workflow": "Build and Release", + "github_actor": "john-doe", + "github_event_name": "release", + "github_server_url": "https://github.com" + }, + "generated_at": "2025-09-28T15:23:57.878282Z", + "ci_job_url": "https://github.com/owner/repo/actions/runs/987654321" + } +} +``` + +To disable build metadata inclusion, set `include-build-metadata` to `false`: + +```yaml +- uses: facebook/dotslash-publish-release@v1 + with: + config: .github/workflows/dotslash-config.json + tag: ${{ github.event.workflow_run.head_branch }} + include-build-metadata: false +``` + ## License dotslash-publish-release is [MIT licensed](./LICENSE). diff --git a/action.yml b/action.yml index afcb214..287dcd8 100644 --- a/action.yml +++ b/action.yml @@ -7,6 +7,10 @@ inputs: tag: description: tag identifying the release whose assets should be used required: true + include-build-metadata: + description: include build metadata in the generated DotSlash files + required: false + default: 'true' runs: using: docker image: Dockerfile @@ -16,3 +20,5 @@ runs: - '--tag' - ${{ inputs.tag }} - '--upload' + - '--include-build-metadata' + - ${{ inputs.include-build-metadata }} diff --git a/process_config.py b/process_config.py index 3e16983..42703bf 100755 --- a/process_config.py +++ b/process_config.py @@ -12,6 +12,7 @@ import re import subprocess import sys import tempfile +import datetime from functools import cache from typing import Any, Dict, Literal, Optional, Tuple, Union @@ -26,6 +27,47 @@ EXCLUDE_HTTP_PROVIDER_PARAM = "exclude-http-provider" EXCLUDE_GITHUB_PROVIDER_PARAM = "exclude-github-release-provider" +def collect_build_metadata(config_path: str) -> Dict[str, Any]: + """Collect build metadata from GitHub Actions environment variables.""" + metadata = {} + + # Source file information + if config_path: + metadata["source_config"] = config_path + + # CI/GitHub Actions information + github_env_vars = [ + ("github_repository", "GITHUB_REPOSITORY"), + ("github_ref", "GITHUB_REF"), + ("github_sha", "GITHUB_SHA"), + ("github_run_id", "GITHUB_RUN_ID"), + ("github_run_number", "GITHUB_RUN_NUMBER"), + ("github_workflow", "GITHUB_WORKFLOW"), + ("github_actor", "GITHUB_ACTOR"), + ("github_event_name", "GITHUB_EVENT_NAME"), + ("github_server_url", "GITHUB_SERVER_URL"), + ] + + ci_info = {} + for key, env_var in github_env_vars: + value = os.getenv(env_var) + if value: + ci_info[key] = value + + if ci_info: + metadata["ci"] = ci_info + + # Build timestamp + metadata["generated_at"] = datetime.datetime.utcnow().isoformat() + "Z" + + # Add link to the CI job if we have the necessary info + if all(os.getenv(var) for var in ["GITHUB_SERVER_URL", "GITHUB_REPOSITORY", "GITHUB_RUN_ID"]): + job_url = f"{os.getenv('GITHUB_SERVER_URL')}/{os.getenv('GITHUB_REPOSITORY')}/actions/runs/{os.getenv('GITHUB_RUN_ID')}" + metadata["ci_job_url"] = job_url + + return metadata + + def main() -> None: exit_code = _main() sys.exit(exit_code) @@ -93,6 +135,23 @@ def _main() -> int: logging.info("using config:") logging.info(json.dumps(config, indent=2)) + # Collect build metadata from the environment + build_metadata = None + + # Convert string argument to boolean + include_metadata_str = str(args.include_build_metadata).lower() + include_metadata = include_metadata_str not in ["false", "0", "no"] and not args.exclude_build_metadata + + # Also check for environment variable (for Docker action support) + include_metadata_env = os.getenv("INCLUDE_BUILD_METADATA", "true").lower() + if include_metadata_env in ["false", "0", "no"]: + include_metadata = False + + if include_metadata: + build_metadata = collect_build_metadata(args.config) + logging.info("build metadata:") + logging.info(json.dumps(build_metadata, indent=2)) + name_to_asset = get_release_assets(tag=tag, github_repository=repo) logging.info(json.dumps(name_to_asset, indent=2)) @@ -111,6 +170,7 @@ def _main() -> int: platform_entries, include_http_provider=not exclude_http_provider, include_github_release_provider=not exclude_github_release_provider, + build_metadata=build_metadata, ) logging.info(manifest_file_contents) @@ -150,6 +210,7 @@ def generate_manifest_file( platform_entries, include_http_provider: bool, include_github_release_provider: bool, + build_metadata: Optional[Dict[str, Any]] = None, ) -> str: platforms = {} with tempfile.TemporaryDirectory() as temp_dir: @@ -224,6 +285,10 @@ def generate_manifest_file( "name": name, "platforms": platforms, } + + # Add build metadata if available + if build_metadata: + manifest["build_metadata"] = build_metadata return f"""#!/usr/bin/env dotslash @@ -458,6 +523,19 @@ def parse_args(): default=os.getenv("GITHUB_WORKSPACE"), ) + parser.add_argument( + "--include-build-metadata", + type=str, + default="true", + help="include build metadata in the generated DotSlash files (default: true)", + ) + + parser.add_argument( + "--exclude-build-metadata", + action="store_true", + help="exclude build metadata from the generated DotSlash files", + ) + return parser.parse_args()