DEV Community

Krishna Pravin
Krishna Pravin

Posted on

How to edit files in a Heroku dyno and persist it

If you edit files present in a Heroku dyno, the edited file comes back to its initial state after some time. This is because Heroku restarts the dynos randomly for keeping them in good health.

Heroku Deployment Process:

skip this if you are familiar

  1. Initiating deployment:
    • Heroku deployment can be triggered manually or it can be configured to get triggered automatically by connecting Heroku to GitHub.
  2. During deployment:
    • Heroku builds the application based on default settings or based on the configured build packs.
    • At the end of this process, a slug will be created. A slug is nothing but the files that were generated during the build. A slug is similar to a docker image (not exactly).
  3. The created slug is deployed in AWS EC2 instances, which is called as dynos by Heroku.
  4. At random intervals, the slug is redeployed for maintaining the health of the dynos #ref

πŸ‘†This is the reason why files edited in a dyno will be reset to its initial state.

πŸ‘»

So, How can we make changes to the files in a Heroku dyno which does not reset to its previous version?

One straightforward solution is to make the changes in the source code and redeploy the application.

Yes, this is one way of achieving it.

But, You may wonder why there would be another scenario. One rare scenario is: You want to change a HTML file (urgent client requirement) that is already part of an application in the production environment, but your build process is getting timed out and you are not able to find the reason.

So, The other solution is:

By editing the previously generated slug and using the edited slug in the required application/environment.

Steps to edit the slug and deploy it:

(100% no build process is required)

  1. Download Heroku CLI
  2. Login to your Heroku account using the CLI
    • $ heroku login
    • This will take you to a browser to fill the login form.
  3. List all the deployed applications
    • $ heroku list --all
  4. Get the unique slug identifier and version number
    • $ heroku slugs -a your_application_name
    • Use the name of the application which has the files you want to edit.
    • You will get all the unique slug identifiers along with their version numbers that are generated and used by your application until now.
    • This version number can be verified from the dashboard https://dashboard.heroku.com/apps/your_application_name/activity
    • If you have too many deployments, store the list to a file
    • $ heroku slugs -a your_application_name > slugsList.txt
  5. Download the slug
    • To download, you need an additional Heroku CLI plugin
    • Install the additional plugin using heroku plugins:install heroku-slugs
    • Then $ heroku slugs:download your_unique_slug_identifier -a your_application_name
    • This will download and create a folder with the name of your application.
    • The created folder will contain a directory called app which contains the generated source code and a slug.tar.gz file, which is the compressed version the source code.
  6. Edit the required files present within the ./app directory.
  7. Create new slug archive
    • Heroku currently has limited tar-file compatibility. Please use GNU Tar (and not bsdtar) when creating slug archives. You can check your tar version with tar --version.
    • While running the below command, you should be in the same directory level as that of ./app directory.
    • $ tar czfv slug.tgz ./app
    • slug.tgz is the name of the archive that will be created
    • c - create, z - gzip format, v - show status, f - file name and location
  8. Create a unique identifier for the new slug
    • $ curl -X POST \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/vnd.heroku+json; version=3' \
      -d '{"process_types":{"your_process_type":"your_command"}}' \
      -n https://api.heroku.com/apps/your_application_name/slugs
      
    • If you don't know your process type(s) and the respective commands, then go to https://dashboard.heroku.com/apps/your_application_name/resources process types
    • For my application, I have two process types. So I will be sending this data in the API call

      {"process_types":{"web": "bundle exec puma -p $PORT -C ./config/puma.rb", "worker": "bundle exec rake jobs:work"}}

    • -n flag tells curl to read the credentials for api.heroku.com from ~/.netrc and automatically sets the Authorization header.
    • -H flag sets the respective header
    • -d flag represents the data to be sent in HTTP POST request
    • You will get a response like this
      • {
          "blob":{
            "method": "put",
            "url": "https://s3-external-1.amazonaws.com/herokuslugs/heroku.com/v1/d969e0b3-9892-4567-7642-1aa1d1108bc3?AWSAccessKeyId=AKIAJWLOWWHPBWQOPJZQ&Signature=2oJJEtemTp7h0qTH2Q4B2nIUY9w%3D&Expires=1381273352"
          },
          "commit":null,
          "created_at":"2013-10-08T22:04:13Z",
          "id":"d969e0b3-9892-3113-7653-1aa1d1108bc3",
          "process_types":{
            "web":"node-v0.10.20-linux-x64/bin/node web.js"
          },
          "updated_at":"2013-10-08T22:04:13Z"
        }
        
    • blob.url - AWS S3 URL for the new slug
    • id - Unique identifier for the new slug
    • Heroku docs reference
  9. Upload the created slug archive to AWS S3
    • $ curl -X PUT \
      -H "Content-Type:" \
      --data-binary @slug.tgz \
      "https://your_aws_s3_blob_url"
      
    • slug.tgz is the name of the archive file we have created.
  10. Create a new release for your application which will use the new slug archive which we have created and uploaded to AWS S3
    • $ curl -X POST \
      -H "Accept: application/vnd.heroku+json; version=3" \
      -H "Content-Type: application/json" \
      -d '{"slug":"your_unique_identifier_of_new_slug"}' \
      -n https://api.heroku.com/apps/your_application_name/releases
      
  11. You can verify the release status in the Heroku dashboard or using heroku releases --app your_application_name

Top comments (6)

Collapse
 
canbax profile image
yusuf

I have a Heroku app which is connected to a GitHub repo. I want to add a file in Heroku. I can do that by using bash command from Heroku cli.

Does the generated file persist? For example when I made a push to my GitHub repo

Collapse
 
askrishnapravin profile image
Krishna Pravin

To add a file to Heroku app, you can push your file to your connected GitHub account.

  • Then if you have enabled Automatic deploys deployment will start.
  • But if you have not enabled auto deploys you have to manually trigger the build.

You can check these settings here: dashboard.heroku.com/apps/your_app...

When this deployment succeeds, your new file will become persistently available in your App.

Collapse
 
canbax profile image
yusuf

but I don't want to push the file to Github. It is a config file, it will be different based on deployment environment

Thread Thread
 
askrishnapravin profile image
Krishna Pravin

Use the Heroku config vars option for environment-specific values.

devcenter.heroku.com/articles/conf...

Thread Thread
 
canbax profile image
yusuf

I think I can't. I'm reading value inside JS code, it should be a file

Thread Thread
 
sayhicoelho profile image
Renan Coelho

Did you find the solution?