{"id":21491646,"url":"https://github.com/unlyed/github-action-store-variable","last_synced_at":"2025-08-02T19:09:15.425Z","repository":{"id":42473094,"uuid":"327572754","full_name":"UnlyEd/github-action-store-variable","owner":"UnlyEd","description":"Easily persist and read variables to reuse them between GitHub Action jobs","archived":false,"fork":false,"pushed_at":"2025-02-04T06:48:55.000Z","size":25336,"stargazers_count":20,"open_issues_count":2,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-16T11:20:40.859Z","etag":null,"topics":["github-actions","persistence","persistent-storage","stores","variables"],"latest_commit_sha":null,"homepage":"https://github.com/marketplace/actions/store-variables","language":"JavaScript","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/UnlyEd.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":{"liberapay":"unlyEd"}},"created_at":"2021-01-07T10:05:58.000Z","updated_at":"2025-03-24T17:47:35.000Z","dependencies_parsed_at":"2025-07-15T19:10:15.383Z","dependency_job_id":"ef0b4966-9de7-4f54-9947-fd181926321c","html_url":"https://github.com/UnlyEd/github-action-store-variable","commit_stats":{"total_commits":77,"total_committers":4,"mean_commits":19.25,"dds":0.4415584415584416,"last_synced_commit":"fca85a566c290a8382989fdb537f716215a8d80c"},"previous_names":[],"tags_count":116,"template":false,"template_full_name":null,"purl":"pkg:github/UnlyEd/github-action-store-variable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnlyEd%2Fgithub-action-store-variable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnlyEd%2Fgithub-action-store-variable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnlyEd%2Fgithub-action-store-variable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnlyEd%2Fgithub-action-store-variable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UnlyEd","download_url":"https://codeload.github.com/UnlyEd/github-action-store-variable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnlyEd%2Fgithub-action-store-variable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268439618,"owners_count":24250671,"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","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["github-actions","persistence","persistent-storage","stores","variables"],"created_at":"2024-11-23T15:17:15.452Z","updated_at":"2025-08-02T19:09:15.398Z","avatar_url":"https://github.com/UnlyEd.png","language":"JavaScript","funding_links":["https://liberapay.com/unlyEd"],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://unly.org\"\u003e\u003cimg src=\"https://storage.googleapis.com/unly/images/ICON_UNLY.png\" align=\"right\" height=\"20\" alt=\"Unly logo\" title=\"Unly logo\" /\u003e\u003c/a\u003e\n[![Maintainability](https://api.codeclimate.com/v1/badges/9e073b5db2eec4c4e5c8/maintainability)](https://codeclimate.com/github/UnlyEd/github-action-store-variable/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/9e073b5db2eec4c4e5c8/test_coverage)](https://codeclimate.com/github/UnlyEd/github-action-store-variable/test_coverage)\n\n![GitHub Action integration test](https://github.com/UnlyEd/github-action-store-variable/workflows/GitHub%20Action%20integration%20test/badge.svg)\n![GitHub Action build test](https://github.com/UnlyEd/github-action-store-variable/workflows/GitHub%20Action%20build%20test/badge.svg)\n![Update Code Climate test coverage](https://github.com/UnlyEd/github-action-store-variable/workflows/Update%20Code%20Climate%20test%20coverage/badge.svg)\n\n# GitHub Action - Store variables between your jobs\n\n## Overview\n\nThis GitHub Action was originally created **in 2021** to allow you to **store variables** in a global store and then **read them in\nlater jobs**—something that was not natively possible in GitHub Actions. It automatically adds read variables to\nyour `${{ env }}` so that they become available for subsequent steps.\n\n## But… GitHub Actions native outputs make this library largely unnecessary!\n\n### What Are Native Outputs?\n\nGitHub Actions now provides native support for sharing data between jobs through the use of step outputs and job\noutputs. You can:\n\n- **Set a step output:** Write key/value pairs to `$GITHUB_OUTPUT` in a step.\n- **Define job outputs:** Map outputs from a step to a job-level output.\n- **Access job outputs:** In downstream jobs, access these outputs using the `needs` context.\n\nSimilarly, the `$GITHUB_ENV` file allows you to persist environment variables across steps in the same job.\n\nSource: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs\n\n### Why Is This a Game Changer?\n\nOriginally, this library provided a way to emulate global variable sharing:\n\n- **Before:** GitHub Actions did not support sharing environment variables between jobs.\n- **Now:** Native outputs let you write a variable in one job and read it in another without extra actions or artifacts.\n\nThis native support simplifies your workflows, reduces dependencies, and improves reliability.\n\n---\n\n## Converting a Use Case\n\n### Old Approach (Using `UnlyEd/github-action-store-variable`) - ⚠️ DEPRECATED\n\nBelow is an example of how you might have stored and retrieved a variable with the library:\n\n```yaml\njobs:\n  compute-data:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Compute data\n        run: |\n          MY_VAR=\"Hello, World!\"\n          echo \"MY_VAR=$MY_VAR\" \u003e\u003e $GITHUB_ENV\n\n      - name: Store variable using the library\n        uses: UnlyEd/github-action-store-variable@v2.1.0\n        with:\n          variables: |\n            MY_VAR=${{ env.MY_VAR }}\n\n  use-data:\n    runs-on: ubuntu-22.04\n    needs: compute-data\n    steps:\n      - name: Retrieve variable using the library\n        uses: UnlyEd/github-action-store-variable@v2.1.0\n        with:\n          variables: |\n            MY_VAR\n      - name: Use variable\n        run: echo \"MY_VAR is $MY_VAR\"\n```\n\n### New Approach (Using Native Outputs)\nHere’s how you can achieve the same result without an external action:\n\n```yaml\njobs:\n  compute-data:\n    runs-on: ubuntu-22.04\n    outputs:\n      MY_VAR: ${{ steps.set-output.outputs.MY_VAR }}\n    steps:\n      - name: Compute data\n        run: |\n          MY_VAR=\"Hello, World!\"\n          echo \"MY_VAR=$MY_VAR\" \u003e\u003e $GITHUB_ENV\n\n      - name: Set step output\n        id: set-output\n        run: |\n          # Export MY_VAR as a step output, so it can be mapped to the job output\n          echo \"MY_VAR=${MY_VAR}\" \u003e\u003e $GITHUB_OUTPUT\n\n  use-data:\n    runs-on: ubuntu-22.04\n    needs: compute-data\n    steps:\n      - name: Use variable from job outputs\n        run: echo \"MY_VAR is ${{ needs.compute-data.outputs.MY_VAR }}\"\n\n```\n\n---\n\n# Former documentation\n\n## Code snippet example (minimal example)\n\n```yaml\nname: 'GitHub Action code snippet'\non:\n  push:\n\njobs:\n  # On some job, do some stuff and persist variables meant to be re-used in other jobs\n  compute-data:\n    name: Compute data\n    runs-on: ubuntu-22.04\n    steps:\n      # Do your own internal business logic...\n      - name: Compute resources\n        run: |\n          MAGIC_NUMBER=42\n          echo \"Found universal answer: $MAGIC_NUMBER\"\n          echo \"Exporting it as ENV variable...\"\n          echo \"MAGIC_NUMBER=$MAGIC_NUMBER\" \u003e\u003e $GITHUB_ENV\n\n      # XXX We recommend to export all your variables at once, at the end of your job\n      - name: Export variable MAGIC_NUMBER for next jobs\n        uses: UnlyEd/github-action-store-variable@v3 # See https://github.com/UnlyEd/github-action-store-variable\n        with:\n          # Persist (store) our MAGIC_NUMBER ENV variable into our store, for the next jobs\n          variables: |\n            MAGIC_NUMBER=${{ env.MAGIC_NUMBER }}\n\n  # In another job, read the previously stored variable and use it\n  retrieve-data:\n    name: Find \u0026 re-use data\n    runs-on: ubuntu-22.04\n    needs: compute-data\n    steps:\n      - name: Import variable MAGIC_NUMBER\n        uses: UnlyEd/github-action-store-variable@v3 # See https://github.com/UnlyEd/github-action-store-variable\n        with:\n          # List all variables you want to retrieve from the store\n          # XXX They'll be automatically added to your ENV\n          variables: |\n            MAGIC_NUMBER\n      - name: Debug output\n        run: echo \"We have access to $MAGIC_NUMBER\"\n```\n\n\u003e If you want to see a real output, check out the output of our code snippet example [here](https://github.com/UnlyEd/github-action-store-variable/actions/runs/537556204).\n\nSee the [Examples section](#examples) for more advanced examples.\n\n## What does this GitHub Action do?\n\nYou can use this action to **store variables** in a sort of \"global store\" for your GitHub Actions.\n\nThen, you can **read the variables** that have been stored previously.\n\nThe variables stored can be read by any job within the same workflow.\n\n\u003e **N.B**: When you read a variable, **it is automatically added as an ENV variable** and will erase any variable with the same name.\n\u003e \n\u003e This behavior helps keeping the code cleaner by only manipulating (reading/writing) ENV variables.\n\u003e In v1, we had to read the variables from a JSON object, and [it was ugly](https://github.com/UnlyEd/github-action-store-variable/blob/c4143c0d7f/.github/workflows/run-integration-test.yml#L29).\n\n\u003e N.B: You can both **read and write** in the same action.\n\n## Why/when should you use it?\n\nGitHub Actions doesn't allow to natively re-use variables between jobs.\n\nIf you need to **re-use variables defined in a job in other** (subsequent) jobs, then you can use this action.\n\n### Action's API\n\n#### Inputs\n\nName | Required | Default | Description\n---  | --- |--- |---\n`variables`|✅| | Write variable: `VAR=VALUE` - Read variable: `VAR`\n`delimiter`|✖️|`\\r?\\n`| Regex delimiter between each variable, defaults to normal line break\n`failIfNotFound`|✖️|`false`| If true, will throw an error (and crash CI) when attempting to read a variable that doesn't exist in the store\n\n#### Outputs\n\nThere are no outputs for this action, reading variables **automatically** adds these variables in `${{ env }}`.\n\nFor example, if you read a variable named `VAR`, you can then access it by using `${{ env.VAR }}`.\n\n## Examples\n\n### 1. Save one variable\n\n```yaml\n- name: Export one variable\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    variables: FOO=BAR\n```\n\n### 2. Save many variables\n\n```yaml\n- name: Export many variables\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    variables: |\n      FOO=BAR\n      STAGE=production\n```\n\n\u003e Pro-tip: We recommend always using the `variables: |` syntax (multi lines), because it's just simpler to add more variables later on.\n\n### 3. Save one variable and read another\n\n```yaml\n- name: Export one variable\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    # Writes \"FOO\" and reads \"STAGE\"\n    variables: |\n      FOO=BAR\n      STAGE\n```\n\n### 4. Save many variables using a custom delimiter\n\n```yaml\n- name: Export many variables\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    delimiter: ':'\n    variables: FOO=BAR:STAGE=production\n```\n\n### 5. Retrieve one variable\n\n```yaml\n- name: Import variable MAGIC_NUMBER\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    variables: FOO\n```\n\n### 6. Retrieve many variables\n\n```yaml\n- name: Import variable MAGIC_NUMBER\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    variables: |\n      FOO\n      STAGE\n```\n\n### 7. Retrieve many variables using a custom delimiter\n\n```yaml\n- name: Import variable MAGIC_NUMBER\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    delimiter: ';'\n    variables: FOO;STAGE\n```\n\n### 8. Crash CI if variable doesn't exist\n\n```yaml\n- name: Import variable MAGIC_NUMBER\n  uses: UnlyEd/github-action-store-variable@v2.1.0\n  with:\n    failIfNotFound: true\n    variables: WRONG_VARIABLE\n```\n\n\u003e N.B: If you want to crash only for some variables, then you can call 2 times the `UnlyEd/github-action-store-variable` and have `failIfNotFound: true` in one of them.\n\n## :hugs: Community examples :heart:\n\nHere are a few community-powered examples, those are usually advanced use-cases!\n\n- [Next Right Now](https://github.com/UnlyEd/next-right-now/blob/60455642a5c5248c3e0e9604de080e24ef9eed0a/.github/workflows/deploy-vercel-staging.yml#L250-L260) _(Disclosure: We're the author!)_\n\n---\n\n# Advanced debugging\n\n\u003e Learn how to enable logging, from within the `github-action-store-variable` action.\n\n## How to enable debug logs\n\nOur GitHub Action is written using the GitHub Actions\nnative [`core.debug` API](https://github.com/actions/toolkit/blob/main/docs/action-debugging.md#step-debug-logs).\n\nTherefore, it allows you to enable logging whenever you need to debug **what's happening within our action**.\n\n**To enable debug mode**, you have to set a [**GitHub Secret**](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets#creating-encrypted-secrets), such as:\n\n- `ACTIONS_STEP_DEBUG` of value `true`\n\nPlease see [the official documentation](https://github.com/actions/toolkit/blob/main/docs/action-debugging.md#how-to-access-step-debug-logs) for more information.\n\n\u003e Enabling debugging using `ACTIONS_STEP_DEBUG` will also enable debugging for all other GitHub Actions you use that are using the `core.debug` API.\n\n---\n\n# Contributing\n\nWe gladly accept PRs, but please open an issue first, so we can discuss it beforehand.\n\n---\n\n# Changelog\n\n[Changelog](./CHANGELOG.md)\n\n---\n\n# Releases versioning\n\nWe follow Semantic Versioning. (`major.minor.patch`)\n\nOur versioning process is completely automated, any changes landing on the `main` branch will trigger a new [release](../../releases).\n\n- `(MAJOR)`: Behavioral change of the existing API that would result in a breaking change.\n  - E.g: Removing an input, or changing the output would result in a breaking change and thus would be released as a new MAJOR version.\n- `(MINOR)`: Behavioral change of the existing API that would **not** result in a breaking change.\n  - E.g: Adding an optional input would result in a non-breaking change and thus would be released as a new MINOR version.\n- `Patch`: Any other change.\n  - E.g: Documentation, tests, refactoring, bug fix, etc.\n\n## Releases versions:\n\nThe examples above use an auto-updated major version tag (`@v1`).\nIt is also possible to use the `@latest` tag.  (RC stands for \"Release candidate\", which is similar to a Beta version)\n\nWhile those options can be useful, we intend to give some \"production-grade\" best practices.\n\n- **Do NOT use `@latest` for production**, ever. While only \"supposed-to-be-stable\" versions will be tagged\n  as `@latest`, it could harbor bugs nonetheless.\n- You can use auto-upgrading major version, such as `@v1` or `@v1.2`, but this is not always the best practice, see our explanations below.\n\n### Special tags and best practices for production-grade apps\n\nHere are a few useful options you can use to pin a more-or-less specific version of our GitHub Action, alongside some \"\nproduction-grade\" best practices.\n\n- `@{COMMIT-SHA}`, e.g: `@1271dc3fc4c4c8bc62ba5a4e248dac95cb82d0e3`, recommended for all production-grade apps, it's the\n  only truly safe way to pinpoint a version that cannot change against your will (**SAFEST**)\n- `@{MAJOR}-{MINOR}-{PATCH}`, e.g: `@v1.2.31`, while not as safe as the `COMMIT-SHA` way, it's what most people use (\n  SAFER)\n- `@{MAJOR}`, e.g: `@v1`, can be used on production, but we do not advise to do so (SAFE-ISH)\n- `@{MAJOR}-rc`, e.g: `@v1-rc`, **reserved for development mode**, useful when debugging on a specific prerelease\n  version (UNSAFE)\n- `@{MAJOR}.{MINOR}`, e.g: `@v1.2`, can be used on production, but we do not advise to do so (SAFE-ISH)\n- `@{MAJOR}.{MINOR}-rc`, e.g: `@v1.2-rc`, **reserved for development mode**, useful when debugging on a specific prerelease\n  version (UNSAFE)\n- `@latest`, **reserved for development mode**, useful when debugging (UNSAFE)\n\n**\"But, what is the issue with the `@{MAJOR}-{MINOR}-{PATCH}` way to pin a specific version\"?**\n\n\u003e Well, if this repository gets hacked by a 3rd party, **they can easily change all Git tags to a different commit**,\nwhich could contain malicious code.\n\nThat's why **pinning a specific commit SHA is the only truly safe option**. This way, the code you're using **cannot be\nchanged against your will**.\n\nMost people won't care about this and will use a MAJOR version tag instead anyway, such as `@v1`. It's common, but not\noften the best practice.\n\nIt all comes down to the risks you're ready to take, and it's up to you to decide what's best in your situation.\n\n---\n\n# License\n\n[MIT](./LICENSE)\n\n---\n\n# Vulnerability disclosure\n\n[See our policy](https://github.com/UnlyEd/Unly).\n\n---\n\n# Contributors and maintainers\n\nThis project is being authored by:\n\n- [Unly] Ambroise Dhenain ([Vadorequest](https://github.com/vadorequest)) **(active)**\n- Hugo Martin ([Demmonius](https://github.com/demmonius)) **(active)**\n\n---\n\n# **[ABOUT UNLY]** \u003ca href=\"https://unly.org\"\u003e\u003cimg src=\"https://storage.googleapis.com/unly/images/ICON_UNLY.png\" height=\"40\" align=\"right\" alt=\"Unly logo\" title=\"Unly logo\" /\u003e\u003c/a\u003e\n\n\u003e [Unly](https://unly.org) is a socially responsible company, fighting inequality and facilitating access to higher education.\n\u003e Unly is committed to making education more inclusive, through responsible funding for students.\n\nWe provide technological solutions to help students find the necessary funding for their studies.\n\nWe proudly participate in many TechForGood initiatives. To support and learn more about our actions to make education accessible, visit :\n\n- https://twitter.com/UnlyEd\n- https://www.facebook.com/UnlyEd/\n- https://www.linkedin.com/company/unly\n- [Interested to work with us?](https://jobs.zenploy.io/unly/about)\n\nTech tips and tricks from our CTO on our [Medium page](https://medium.com/unly-org/tech/home)!\n\n# TECHFORGOOD #EDUCATIONFORALL\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funlyed%2Fgithub-action-store-variable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funlyed%2Fgithub-action-store-variable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funlyed%2Fgithub-action-store-variable/lists"}