{"id":49680244,"url":"https://github.com/bcgov/action-builder-ghcr","last_synced_at":"2026-05-07T06:04:50.695Z","repository":{"id":63195232,"uuid":"563943232","full_name":"bcgov/action-builder-ghcr","owner":"bcgov","description":"GitHub Action.  Build if triggered, else use fallback image.  Push to ghcr.io.","archived":false,"fork":false,"pushed_at":"2026-05-07T01:28:15.000Z","size":143,"stargazers_count":4,"open_issues_count":3,"forks_count":10,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-07T01:29:32.798Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bcgov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/codeowners","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-11-09T16:57:20.000Z","updated_at":"2026-05-07T01:25:12.000Z","dependencies_parsed_at":"2026-01-16T02:04:02.400Z","dependency_job_id":null,"html_url":"https://github.com/bcgov/action-builder-ghcr","commit_stats":{"total_commits":14,"total_committers":3,"mean_commits":4.666666666666667,"dds":0.1428571428571429,"last_synced_commit":"a9f54ebec1ce41a5cda0bc656af4561606bd09fd"},"previous_names":["bcgov/action-builder-ghcr","bcgov-nr/action-builder-ghcr","bcgov-nr/action-conditional-container-builder"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/bcgov/action-builder-ghcr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Faction-builder-ghcr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Faction-builder-ghcr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Faction-builder-ghcr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Faction-builder-ghcr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bcgov","download_url":"https://codeload.github.com/bcgov/action-builder-ghcr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Faction-builder-ghcr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32725218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-05-07T06:04:49.510Z","updated_at":"2026-05-07T06:04:50.622Z","avatar_url":"https://github.com/bcgov.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- Badges --\u003e\n[![Issues](https://img.shields.io/github/issues/bcgov/action-builder-ghcr)](/../../issues)\n[![Pull Requests](https://img.shields.io/github/issues-pr/bcgov/action-builder-ghcr)](/../../pulls)\n[![MIT License](https://img.shields.io/github/license/bcgov/action-builder-ghcr.svg)](/LICENSE)\n[![Lifecycle](https://img.shields.io/badge/Lifecycle-Experimental-339999)](https://github.com/bcgov/repomountie/blob/master/doc/lifecycle-badges.md)\n\n# Conditional Container Builder with Fallback, Attestations and SBOMs (Software Bill of Materials)\n\nThis action builds Docker/Podman containers conditionally using a set of directories.  If any files were changed matching that, then build a container.  If those files were not changed, retag an existing build.\n\nThis is useful in CI/CD pipelines where not every package/app needs to be rebuilt.\n\nThis tool is currently strongly opinionated and generates images with a rigid structure below.  This is intended to become more flexible in future.\n\nPackage name: `\u003corganization\u003e/\u003crepository\u003e/\u003cpackage\u003e:\u003ctag\u003e`\n\nPull with: `docker pull ghcr.io/\u003corganization\u003e/\u003crepository\u003e/\u003cpackage\u003e:\u003ctag\u003e` \n\nOnly GitHub Container Registry (ghcr.io) is supported so far.\n\n# Usage\n\n```yaml\n- uses: bcgov/action-builder-ghcr@vX.Y.X\n  with:\n    ### Required\n\n    # Package name\n    package: frontend\n\n\n    ### Typical / recommended\n\n    # Sets the build context/directory, which contains the build files\n    # Optional, defaults to package name\n    build_context: ./frontend\n\n    # Sets the Dockerfile with path\n    # Optional, defaults to {package}/Dockerfile or {build_context}/Dockerfile\n    build_file: ./frontend/Dockerfile\n\n    # Fallback tag, used if no build was generated\n    # Optional, defaults to nothing, which forces a build\n    # Non-matching or malformed tags are rejected, which also forced a build\n    tag_fallback: test\n\n    # Tags to apply to the image\n    # Optional, defaults to pull request number\n    # Note: All tags are normalized to lowercase and stripped of spaces before use.\n    tags: |\n      pr123\n      demo\n\n    # Bash array to diff for build triggering\n    # Optional, defaults to nothing, which forces a build\n    triggers: ('frontend/' 'backend/' 'database/')\n\n\n    ### Usually a bad idea / not recommended\n\n    # Sets a list of [build-time variables](https://docs.docker.com/engine/reference/commandline/buildx_build/#build-arg)\n    # Optional, defaults to sample content\n    build_args: |\n      ENV=build\n\n    # Overrides the default branch to diff against\n    # Defaults to the default branch, usually `main`\n    diff_branch: ${{ github.event.repository.default_branch }}\n\n    # Repository to clone and process\n    # Useful for consuming other repos, like in testing\n    # Defaults to the current one\n    repository: ${{ github.repository }}\n\n    # SBOM generation is enabled by default as a security best practice\n    # String value, not boolean\n    sbom: 'true'\n\n    # Specify token (GH or PAT), instead of inheriting one from the calling workflow\n    token: ${{ secrets.GITHUB_TOKEN }}\n\n    # Specify username for registry login; defaults to github.actor\n    # Useful when using a PAT or service account\n    username: ${{ github.actor }}\n\n    # Multiline input for secrets to mount.\n    # https://docs.docker.com/build/ci/github-actions/secrets/#secret-mounts\n    secrets: |\n        MY_SECRET=${{ secrets.MY_SECRET }}\n        ANOTHER_SECRET=${{ secrets.ANOTHER_SECRET }}\n\n    # Enable automatic tag and label generation using docker/metadata-action\n    # Enabled by default. Set to 'false' to disable.\n    # metadata_tag_rules defaults are used if not provided.\n    metadata_tags: 'true'\n\n    # Flavor configuration for metadata-action (optional)\n    # Only used when metadata_tags is enabled\n    metadata_flavor: |\n        latest=true\n\n    # Custom tag rules for metadata-action (optional)\n    # Only used when metadata_tags is enabled\n    # Sensible defaults are provided; override with your own rules if needed\n    metadata_tag_rules: |\n        type=sha,format=short\n        type=ref,event=branch\n        type=ref,event=pr\n        type=raw,value=latest,enable={{is_default_branch}}\n        type=semver,pattern={{version}}\n        type=semver,pattern={{major}}.{{minor}}\n        type=semver,pattern={{major}}\n\n    # SBOM generation is enabled by default as a security best practice\n    # String value, not boolean\n    sbom: 'true'\n\n    ### Deprecated\n\n    # Single-value tag input has been deprecated and will be removed in a future release\n    # Please use inputs.tags, which can handle multiple values\n    tag: do not use!\n\n```\n\n# Private Repository Support\n\nThis action supports building from and pushing to private repositories. \n\n### Authentication\n\n- **Same Repository/Organization**: By default, the action uses the automatic `GITHUB_TOKEN`. Ensure your workflow has `contents: read` and `packages: write` permissions.\n- **Cross-Organization**: To build from a private repository in a different organization, provide a **Personal Access Token (PAT)** with `repo` scope via the `token` input and specify the associated `username`.\n\n### Security\n\nTo prevent credential leakage, this action:\n- Uses `persist-credentials: false` during all checkout steps.\n- Performs a clean registry login using the provided `username` and `token` before any manifest or build operations.\n\n\n# Example, Single Build\n\nBuild a single subfolder with a Dockerfile in it.  Runs on pull requests (PRs).\n\n```yaml\nbuilds:\n  runs-on: ubuntu-24.04\n  steps:\n    - name: Builds\n      uses: bcgov/action-builder-ghcr@vX.Y.Z\n      with:\n        package: frontend\n        tag_fallback: test\n        triggers: ('frontend/')\n```\n\n# Example, Single Build with build_context, build_file and multiple tags\n\nSame as previous, but specifying build folder and Dockerfile.\n\n```yaml\nbuilds:\n  runs-on: ubuntu-24.04\n  steps:\n    - name: Builds\n      uses: bcgov/action-builder-ghcr@vX.Y.Z\n      with:\n        package: frontend\n        build_context: ./\n        build_file: subdir/Dockerfile\n        tags: |\n          ${{ github.event.number }}\n          ${{ github.sha }}\n          latest\n        tag_fallback: test\n        token: ${{ secrets.GITHUB_TOKEN }}\n        triggers: ('frontend/')\n```\n\n# Example, Matrix Build\n\nBuild from multiple subfolders with Dockerfile in them.  This time an outside repository is used.  Runs on pull requests (PRs).\n\n```yaml\nbuilds:\n  runs-on: ubuntu-24.04\n  strategy:\n    matrix:\n      package: [backend, frontend]\n      include:\n        - package: backend\n          triggers: ('backend/')\n        - package: frontend\n          triggers: ('frontend/')\n  steps:\n    - uses: actions/checkout@v4\n    - name: Test Builds\n      uses: bcgov/action-builder-ghcr@vX.Y.Z\n      with:\n        package: ${{ matrix.package }}\n        tags: ${{ github.event.number }}\n        tag_fallback: test\n        repository: bcgov/nr-quickstart-typescript\n        token: ${{ secrets.GITHUB_TOKEN }}\n        triggers: ${{ matrix.triggers }}\n\n```\n\n# Example, Metadata Tags for Automatic Tagging\n\nMetadata tags are enabled by default with sensible tag rules. Override rules or flavor as needed.\n\n```yaml\nbuilds:\n  runs-on: ubuntu-24.04\n  steps:\n    - name: Builds with Metadata Tags\n      uses: bcgov/action-builder-ghcr@vX.Y.Z\n      with:\n        package: frontend\n        tag_fallback: test\n        triggers: ('frontend/')\n        # Override flavor (optional)\n        metadata_flavor: |\n          latest=true\n        # Override tag rules (optional - sensible defaults are used if omitted)\n        metadata_tag_rules: |\n          type=sha,format=short\n          type=ref,event=branch\n          type=ref,event=pr\n          type=raw,value=latest,enable={{is_default_branch}}\n          type=semver,pattern={{version}}\n          type=semver,pattern={{major}}.{{minor}}\n```\n\nDefault tag rules generate tags like:\n- For branch pushes: `main`, `develop`, etc.\n- For PRs: `pr-123`\n- For semver tags: `v1.2.3`, `1.2`, `1`, `latest`\n- For all commits: `sha-abc1234`\n\n# Security Features\n\nThis action provides two key security features: Container Attestations and Software Bill of Materials (SBOM) generation. Additionally, it leverages the `docker/metadata-action` for best-practice container image tagging and labeling.\n\n## Container Metadata and Labeling\n\nThis action uses the [`docker/metadata-action`](https://github.com/docker/metadata-action) to automatically generate OCI-compliant labels and annotations for container images. This ensures that images are tagged and labeled following [Open Container Initiative (OCI) specifications](https://specs.opencontainers.org/image-spec/annotations/) and Docker best practices.\n\nThe following [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/main/annotations.md) labels are automatically added to all container images:\n\n- **org.opencontainers.image.created** - Image creation timestamp (ISO 8601 format)\n- **org.opencontainers.image.url** - URL to the source repository (e.g., https://github.com/bcgov/repo-name)\n- **org.opencontainers.image.source** - URL to the source repository\n- **org.opencontainers.image.version** - Version/tag of the image (e.g., main, pr-123)\n- **org.opencontainers.image.revision** - Git commit SHA that triggered the build\n- **org.opencontainers.image.title** - Human-readable title (repository name)\n- **org.opencontainers.image.description** - Description from the repository\n- **org.opencontainers.image.licenses** - License information from the repository's LICENSE file\n\nThese labels provide standardized metadata for source provenance, attestation, and help ensure baseline security practices for container deployments.\n\n### Example OCI Labels\n\nHere's an example of the OCI labels that would be applied to a container image built with this action:\n\n```json\n{\n  \"org.opencontainers.image.created\": \"2025-05-29T19:09:03.374Z\",\n  \"org.opencontainers.image.url\": \"https://github.com/bcgov/nr-peach\",\n  \"org.opencontainers.image.source\": \"https://github.com/bcgov/nr-peach\",\n  \"org.opencontainers.image.version\": \"main\",\n  \"org.opencontainers.image.revision\": \"fadf03ce2db919752ada03af3f8fb4895fe96fcf\",\n  \"org.opencontainers.image.title\": \"nr-peach\",\n  \"org.opencontainers.image.description\": \"NR Permitting Exchange, Aggregation and Collection Hub\",\n  \"org.opencontainers.image.licenses\": \"Apache-2.0\"\n}\n```\n\nYou can inspect these labels on any built image using:\n```bash\ndocker inspect ghcr.io/org/repo/package:tag | jq '.[0].Config.Labels'\n```\n\n## Container Attestations\n\n[Container attestations](https://docs.github.com/en/actions/security-guides/security-hardening-with-openid-connect#about-oidc-and-container-signing) use GitHub's OIDC token to provide cryptographic proof of:\n- Where the container was built (GitHub Actions)\n- When it was built (timestamp)\n- What repository and workflow built it\n- What inputs and environment were used\n\nAttestations require the following permissions:\n```yaml\npermissions:\n  packages: write      # Required for pushing images\n  id-token: write      # Required for OIDC token generation\n  attestations: write  # Required for creating attestations\n```\n\nIf these permissions are not granted, the action will still build and push images but skip the attestation step.\n\n## Software Bill of Materials (SBOM)\n\nThis action automatically generates SBOMs for all container builds using [Syft](https://github.com/anchore/syft). SBOMs provide a detailed inventory that includes:\n- All installed packages and their versions\n- Dependencies and their relationships\n- License information\n- Known vulnerabilities\n\nTwo SBOM formats are generated and uploaded as workflow artifacts:\n- CycloneDX JSON\n- SPDX JSON\n\n# Outputs\n\n| Output     | Description                                 |\n|------------|---------------------------------------------|\n| `digest`   | Immutable digest (only on fresh builds)     |\n| `triggered`| Whether a build was triggered (`true/false`)|\n| `labels`   | OCI labels generated by metadata-action (when metadata_tags is enabled) |\n| `annotations` | OCI annotations generated by metadata-action (when metadata_tags is enabled) |\n| `registry_host` | The registry host name, always `ghcr.io` |\n| `image_path` | The full image path including the tag, always with a leading slash, in the format `/owner/repo/image:tag` (or `/owner/repo:tag` when the package matches the repository name) |\n\nNew image digest (SHA).  This applies to build and retags.\n\n```yaml\n- id: digest\n  uses: bcgov/action-builder-ghcr@vX.Y.Z\n  ...\n\n- name: Echo digest\n  run: |\n    echo \"Digest: ${{ steps.digest.outputs.digest }}\"\n  ...\n```\n\nHas an image been built?  [true|false]\n\n```yaml\n- id: trigger\n  uses: bcgov/action-builder-ghcr@vX.Y.Z\n  ...\n\n- name: Echo build trigger\n  run: |\n    echo \"Trigger result: ${{ steps.trigger.outputs.triggered }}\"\n  ...\n```\n\n# Image Naming Convention\n\n- Multi package repos: `ghcr.io/org/repo/package:tag`\n- Single package repos: `ghcr.io/org/repo:tag`\n\nSingle package naming is only triggered when package=repository.\n\n# Deprecations\n\n\u003e ⚠️ **Deprecated:** The `tag` input has been deprecated in favor of `tags`, a multiline string that can handle multiple values. The `tag` input will be removed in a future release.\n\n- The `digest_old` output has been deprecated due to non-use.\n- The `digest_new` output has been renamed to `digest`.\n\n\u003c!-- # Acknowledgements\n\nThis Action is provided courtesy of the Forestry Suite of Applications, part of the Government of British Columbia. --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcgov%2Faction-builder-ghcr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbcgov%2Faction-builder-ghcr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcgov%2Faction-builder-ghcr/lists"}