{"id":45138252,"url":"https://github.com/octivi/update-copyright-year","last_synced_at":"2026-02-20T00:13:13.846Z","repository":{"id":335577968,"uuid":"1146307892","full_name":"octivi/update-copyright-year","owner":"octivi","description":"GitHub Action that updates the copyright year in file headers across your repository","archived":false,"fork":false,"pushed_at":"2026-02-19T21:01:16.000Z","size":82,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-19T23:43:53.346Z","etag":null,"topics":["action","automation","ci","code-quality","copyright","github-actions","github-actions-ci","github-actions-workflow","github-actions-workflows","headers","license","maintenance"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/octivi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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":"2026-01-30T22:34:25.000Z","updated_at":"2026-02-19T21:01:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/octivi/update-copyright-year","commit_stats":null,"previous_names":["octivi/update-copyright-year"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/octivi/update-copyright-year","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octivi%2Fupdate-copyright-year","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octivi%2Fupdate-copyright-year/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octivi%2Fupdate-copyright-year/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octivi%2Fupdate-copyright-year/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/octivi","download_url":"https://codeload.github.com/octivi/update-copyright-year/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octivi%2Fupdate-copyright-year/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29637398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"ssl_error","status_checked_at":"2026-02-19T22:32:38.330Z","response_time":117,"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":["action","automation","ci","code-quality","copyright","github-actions","github-actions-ci","github-actions-workflow","github-actions-workflows","headers","license","maintenance"],"created_at":"2026-02-20T00:13:09.490Z","updated_at":"2026-02-20T00:13:13.838Z","avatar_url":"https://github.com/octivi.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Update Copyright Year GitHub Action\n\n[![GitHub Marketplace](https://img.shields.io/badge/GitHub%20Marketplace-blue?logo=github)](https://github.com/marketplace/actions/update-copyright-year)\n[![GitHub Releases](https://img.shields.io/github/v/release/octivi/update-copyright-year?sort=semver)](https://github.com/octivi/update-copyright-year/releases)\n[![License: MIT](https://img.shields.io/github/license/octivi/update-copyright-year)](https://choosealicense.com/licenses/mit/)\n[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org/)\n[![Semantic Versioning](https://img.shields.io/badge/SemVer-2.0.0-blue)](https://semver.org/spec/v2.0.0.html)\n\nGitHub Action that updates the copyright year in file headers across your repository.\n\n## What the project does\n\nScans files in selected directories and updates copyright header years using configurable `sed` regexps.\n\n## Why the project is useful\n\nKeeps year ranges in headers accurate with minimal maintenance, especially for repos with many files or templates.\n\n## Why choose this action\n\n- Pure Bash implementation with minimal dependencies\n- Fast startup: no `npm`/`pip` install step during workflow execution\n- Lower supply-chain and maintenance overhead: no runtime pinning, lockfiles, or dependency CVEs\n- Easier security audit: all logic lives in a small, readable script\n- Covered by automated tests (`./tests/run`) and CI\n- Works on `ubuntu-slim`, which can help reduce runner costs:\n  \u003chttps://docs.github.com/en/actions/reference/runners/github-hosted-runners\u003e\n- Can be used both as a GitHub Action and as a standalone script\n- Released under the MIT License: a short and simple permissive license\n- Documented security policy: [SECURITY.md](./SECURITY.md)\n\n## Getting started\n\n1. Add the action to your workflow (see \"Example workflow\" below).\n2. Optionally set `targets`, `exclude_paths`, `organization_regexp`, and `headers_regexp`.\n3. Run the workflow and review changes (optionally create a PR in your workflow).\n\n## Inputs\n\n| Name                  | Required | Default             | Description                                                                                                                                                           |\n| --------------------- | -------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `targets`             | No       | `.`                 | Directories to scan (space-, comma- or newline-separated), e.g. `. src scripts`                                                                                       |\n| `exclude_paths`       | No       | `.github/workflows` | Paths to exclude (space-, comma- or newline-separated), e.g. `.github/workflows build`. Relative paths are resolved against each target; absolute paths are supported |\n| `include_glob`        | No       | _(empty)_           | Optional glob patterns to include (space-, comma- or newline-separated), e.g. `**/*.{sh,py,js}`                                                                       |\n| `organization_regexp` | No       | _(empty)_           | Optional regexp snippet for the organization/person name after the year (used only when `headers_regexp` is empty)                                                    |\n| `headers_regexp`      | No       | _(see below)_       | Array of `sed` regexps (one per line). Use `{{CURRENT_YEAR}}` as a placeholder                                                                                        |\n| `dry_run`             | No       | `false`             | If `true`, print planned changes without modifying files                                                                                                              |\n| `verbose`             | No       | `false`             | If `true`, print detailed logs                                                                                                                                        |\n\n## CLI usage\n\nRun locally from this repo:\n\n```bash\n./update-copyright-year \\\n  --targets \". src scripts\" \\\n  --exclude-paths \".github/workflows build\" \\\n  --include-glob \"**/*.{sh,py,js}\" \\\n  --organization-regexp \"IMAGIN sp\\. z o\\.o\\.\"\n```\n\nOptions map 1:1 to the action inputs. You can also set them via env vars:\n`TARGETS`, `EXCLUDE_PATHS`, `INCLUDE_GLOB`, `ORGANIZATION_REGEXP`, `HEADERS_REGEXP`, `CURRENT_YEAR`, `DRY_RUN`, `VERBOSE`.\nFor list inputs (`TARGETS`, `EXCLUDE_PATHS`, `INCLUDE_GLOB`) you can separate values with spaces, commas, newlines, or mix these separators.\n`DRY_RUN` and `VERBOSE` are presence flags: any non-empty value enables the mode, leaving the variable unset disables it.\n\nOptional execution modes:\n\n```bash\n./update-copyright-year --dry-run --verbose\n```\n\nWhen run inside GitHub Actions, logs are grouped, warnings/errors are emitted as workflow annotations, and a short result is written to `GITHUB_STEP_SUMMARY`.\n\nDefault `headers_regexp`:\n\n```text\ns/^(.*Copyright[^0-9]*)([0-9]{4})(-[0-9]{4})?([[:space:]]+.*)?$/\\1\\2-{{CURRENT_YEAR}}\\4/\n```\n\nNote: The action always performs a cleanup pass to collapse ranges like `2026-2026` back to `2026`.\nWhen `organization_regexp` is set and `headers_regexp` is empty, the default becomes:\n\n```text\ns/^(.*Copyright[^0-9]*)([0-9]{4})(-[0-9]{4})?([[:space:]]+YOUR_ORG_REGEXP)?$/\\1\\2-{{CURRENT_YEAR}}\\4/\n```\n\nIf `headers_regexp` is provided, it always takes precedence over `organization_regexp`.\nIf you want a literal organization name, escape regexp metacharacters (for example, dots).\n\n## Examples\n\nUpdate regex (default) matches both single years and ranges:\n\n```text\nCopyright 2021-2023\nCopyright (c) 2021-2023\nCopyright 2021-2023 ACME Inc.\n```\n\nAssuming the current year is 2026, the updates become:\n\n```text\nCopyright 2021-2026\nCopyright (c) 2021-2026\nCopyright 2021-2026 ACME Inc.\n```\n\nCleanup regex (always applied) then collapses:\n\n```text\nCopyright 2026-2026\n```\n\nto:\n\n```text\nCopyright 2026\n```\n\n## Customization tips\n\nAdditional regex examples you can pass via `headers_regexp`:\n\n```text\n# Match \"Copyright (c) 2019-2023\" or \"Copyright © 2019\"\ns/^(.*Copyright[^0-9]*)([0-9]{4})(-[0-9]{4})?([[:space:]]+.*)?$/\\1\\2-{{CURRENT_YEAR}}\\4/\n\n# Match \"Copyright 2019, Company\" (commas or extra text at end)\ns/^(.*Copyright[^0-9]*)([0-9]{4})([[:space:]]*,.*)?$/\\1\\2-{{CURRENT_YEAR}}\\3/\n```\n\n## Tests\n\nRun the lightweight test suite (no external deps):\n\n```bash\n./tests/run\n```\n\nSet `CURRENT_YEAR` to make tests deterministic.\n\n## Limitations\n\n- Only files detected as `text/*` by the `file` command are edited\n- Uses GNU `sed` options available on `ubuntu-latest` and `ubuntu-slim` runners\n- Include patterns are Bash globs matched against the file path (with or without a leading `./`)\n- Exclude paths are resolved per target directory; absolute paths are matched as-is\n\n## Example workflow\n\n```yml\nname: Update year in headers\n\non:\n  workflow_dispatch:\n\njobs:\n  update-year:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: octivi/update-copyright-year@v1\n        with:\n          targets: \". src scripts\"\n          exclude_paths: \".github/workflows build\"\n          include_glob: \"**/*.{sh,py,js}\"\n          organization_regexp: \"IMAGIN sp\\\\. z o\\\\.o\\\\.\"\n          # headers_regexp: |\n          #   s/^(.*Copyright[^0-9]*)([0-9]{4})(-[0-9]{4})?([[:space:]]+.*)?$/\\1\\2-{{CURRENT_YEAR}}\\4/\n\n      # Optional: create PR in your own workflow\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@v8\n        with:\n          branch: update-year-in-headers\n          delete-branch: true\n          commit-message: \"chore: Update year in headers\"\n          title: Update year in headers\n          body: |\n            Automated update of year in headers.\n          labels: |\n            automation\n            maintenance\n```\n\n## Getting help\n\nIf you run into issues, open a GitHub issue in this repository and include a minimal reproduction\n(sample file + workflow snippet).\n\n## Other Octivi GitHub Actions\n\nIf you are interested in other GitHub Actions we build, see:\n\n- [`octivi/update-securitytxt-expires`](https://github.com/octivi/update-securitytxt-expires) - Updates the `Expires` field in `security.txt` files to a future date so published security contact metadata stays current\n- [`octivi/cloudflare-cache-purge`](https://github.com/octivi/cloudflare-cache-purge) - Purges Cloudflare cache via Cloudflare API\n- [`octivi/release-notes-from-changelog`](https://github.com/octivi/release-notes-from-changelog) - Extracts Release Notes from Changelog\n\n## Maintainers and contributors\n\nMaintained by the [Octivi DevOps team](https://octivi.com/devops). Contributions are welcome via\npull requests.\n\nBuilt with [Octivi Bash Boilerplate](https://github.com/octivi/bash-boilerplate).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foctivi%2Fupdate-copyright-year","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foctivi%2Fupdate-copyright-year","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foctivi%2Fupdate-copyright-year/lists"}