Heroku deployment not picking up latest settings.py changes

Hi!

I’m using git trying to deploy to a staging pipeline on Heroku.

My build is failing. Based on the traceback (two of them, below), I have a general sense as to why. It involves my dynamic SECRET_KEY configuration variable in settings.py. The traceback refers to a python-decouple module installed previously. So I commented out the import line to that package in settings.py, removed the package from my requirements.txt, and used this instead:

from dotenv import load_dotenv
load_dotenv()
...
SECRET_KEY = str(os.getenv('SECRET_KEY'))

That’s the latest version. When I save my changes, commit them, and then push to the staging pipeline, the traceback being returned refers to line 27 as if is still like this:

from decouple import config
...
SECRET_KEY = config('SECRET_KEY')

I’m not sure why Heroku is not picking up the latest and most recent changes. Any ideas?

Here is my full build traceback:

$ git push staging main
Enumerating objects: 4016, done.
Counting objects: 100% (4016/4016), done.
Delta compression using up to 20 threads
Compressing objects: 100% (3932/3932), done.
Writing objects: 100% (3965/3965), 6.41 MiB | 3.71 MiB/s, done.
Total 3965 (delta 302), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (302/302), completed with 15 local objects.
remote: Updated 7290 paths from c9c269d
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-22 stack
remote: -----> Using buildpack: heroku/python
remote: -----> Python app detected
remote: -----> Using Python version specified in runtime.txt
remote: -----> Python version has changed from python-3.11.2 to python-3.10.10, clearing cache
remote: -----> Requirements file has been changed, clearing cached dependencies
remote: -----> Installing python-3.10.10
remote: -----> Installing pip 23.0.1, setuptools 63.4.3 and wheel 0.38.4
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote:        Collecting asgiref==3.6.0
remote:          Downloading asgiref-3.6.0-py3-none-any.whl (23 kB)
remote:        Collecting certifi==2022.12.7
remote:          Downloading certifi-2022.12.7-py3-none-any.whl (155 kB)
remote:        Collecting charset-normalizer==3.1.0
remote:          Downloading charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (199 kB)
remote:        Collecting dj-database-url==1.3.0
remote:          Downloading dj_database_url-1.3.0-py3-none-any.whl (7.4 kB)
remote:        Collecting django==4.1.8
remote:          Downloading Django-4.1.8-py3-none-any.whl (8.1 MB)
remote:        Collecting django-ckeditor==6.5.1
remote:          Downloading django_ckeditor-6.5.1-py3-none-any.whl (2.4 MB)
remote:        Collecting django-heroku==0.3.1
remote:          Downloading django_heroku-0.3.1-py2.py3-none-any.whl (6.2 kB)
remote:        Collecting django-jazzmin==2.6.0
remote:          Downloading django_jazzmin-2.6.0-py3-none-any.whl (2.8 MB)
remote:        Collecting django-js-asset==2.0.0
remote:          Downloading django_js_asset-2.0.0-py3-none-any.whl (4.9 kB)
remote:        Collecting gunicorn==20.1.0
remote:          Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
remote:        Collecting heroku3==5.2.0
remote:          Downloading heroku3-5.2.0-py2.py3-none-any.whl (161 kB)
remote:        Collecting idna==3.4
remote:          Downloading idna-3.4-py3-none-any.whl (61 kB)
remote:        Collecting pillow==9.5.0
remote:          Downloading Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl (3.4 MB)
remote:        Collecting psycopg2==2.9.6
remote:          Downloading psycopg2-2.9.6.tar.gz (383 kB)
remote:          Preparing metadata (setup.py): started
remote:          Preparing metadata (setup.py): finished with status 'done'
remote:        Collecting python-dateutil==2.8.2
remote:          Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
remote:        Collecting python-dotenv==1.0.0
remote:          Downloading python_dotenv-1.0.0-py3-none-any.whl (19 kB)
remote:        Collecting pytz==2023.3
remote:          Downloading pytz-2023.3-py2.py3-none-any.whl (502 kB)
remote:        Collecting requests==2.28.2
remote:          Downloading requests-2.28.2-py3-none-any.whl (62 kB)
remote:        Collecting six==1.16.0
remote:          Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
remote:        Collecting sqlparse==0.4.3
remote:          Downloading sqlparse-0.4.3-py3-none-any.whl (42 kB)
remote:        Collecting typing-extensions==4.5.0
remote:          Downloading typing_extensions-4.5.0-py3-none-any.whl (27 kB)
remote:        Collecting urllib3==1.26.15
remote:          Downloading urllib3-1.26.15-py2.py3-none-any.whl (140 kB)
remote:        Collecting whitenoise==6.4.0
remote:          Downloading whitenoise-6.4.0-py3-none-any.whl (19 kB)
remote:        Building wheels for collected packages: psycopg2
remote:          Building wheel for psycopg2 (setup.py): started
remote:          Building wheel for psycopg2 (setup.py): finished with status 'done'
remote:          Created wheel for psycopg2: filename=psycopg2-2.9.6-cp310-cp310-linux_x86_64.whl size=159971 sha256=633a65b5bc08894912275e69ae23e45eb18511e0fb0be56037f9da7f9d301ceb
remote:          Stored in directory: /tmp/pip-ephem-wheel-cache-pghrau7m/wheels/a2/65/83/78e6f42d3b8e22115e894576b71799d96ab5a790b8f7bcfa85
remote:        Successfully built psycopg2
remote:        Installing collected packages: pytz, whitenoise, urllib3, typing-extensions, sqlparse, six, python-dotenv, psycopg2, pillow, idna, gunicorn, charset-normalizer, certifi, asgiref, requests, python-dateutil, django, heroku3, django-js-asset, django-jazzmin, dj-database-url, django-heroku, django-ckeditor
remote:        Successfully installed asgiref-3.6.0 certifi-2022.12.7 charset-normalizer-3.1.0 dj-database-url-1.3.0 django-4.1.8 django-ckeditor-6.5.1 django-heroku-0.3.1 django-jazzmin-2.6.0 django-js-asset-2.0.0 gunicorn-20.1.0 heroku3-5.2.0 idna-3.4 pillow-9.5.0 psycopg2-2.9.6 python-dateutil-2.8.2 python-dotenv-1.0.0 pytz-2023.3 requests-2.28.2 six-1.16.0 sqlparse-0.4.3 typing-extensions-4.5.0 urllib3-1.26.15 whitenoise-6.4.0
remote: -----> $ python manage.py collectstatic --noinput
remote:        Found another file with the destination path 'admin/js/popup_response.js'. It will be ignored since only the first encountered file is collected. If this is not what you want, make sure every static file has a unique path.
remote:        Found another file with the destination path 'admin/js/cancel.js'. It will be ignored since only the first encountered file is collected. If this is not what you want, make sure every static file has a unique path.
remote:        Post-processing 'vendor/bootswatch/default/bootstrap.min.css' failed!
remote:        Traceback (most recent call last):
remote:          File "/tmp/build_6ab523f7/manage.py", line 22, in <module>
remote:            main()
remote:          File "/tmp/build_6ab523f7/manage.py", line 18, in main
remote:            execute_from_command_line(sys.argv)
remote:          File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
remote:            utility.execute()
remote:          File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
remote:            self.fetch_command(subcommand).run_from_argv(self.argv)
remote:          File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 402, in run_from_argv
remote:            self.execute(*args, **cmd_options)
remote:          File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 448, in execute
remote:            output = self.handle(*args, **options)
remote:          File "/app/.heroku/python/lib/python3.10/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 209, in handle
remote:            collected = self.collect()
remote:          File "/app/.heroku/python/lib/python3.10/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 154, in collect
remote:            raise processed
remote:        whitenoise.storage.MissingFileError: The file 'vendor/bootswatch/default/bootstrap.min.css.map' could not be found with <whitenoise.storage.CompressedManifestStaticFilesStorage object at 0x7f0bf2f350c0>.
remote:        The CSS file 'vendor/bootswatch/default/bootstrap.min.css' references a file which could not be found:
remote:          vendor/bootswatch/default/bootstrap.min.css.map
remote:        Please check the URL references in this CSS file, particularly any
remote:        relative paths which might be pointing to the wrong location.
remote: 
remote:  !     Error while running '$ python manage.py collectstatic --noinput'.
remote:        See traceback above for details.
remote: 
remote:        You may need to update application code to resolve this error.
remote:        Or, you can disable collectstatic for this application:
remote: 
remote:           $ heroku config:set DISABLE_COLLECTSTATIC=1
remote: 
remote:        https://devcenter.heroku.com/articles/django-assets
remote:  !     Push rejected, failed to compile Python app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !	Push rejected to <project-name>
remote: 
To https://git.heroku.com/<project-name>.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/<project-name>.git'

As you can see, it says: “Error while running ‘$ python manage.py collectstatic --noinput’.
remote: See traceback above for details.” So here is $ python manage.py collectstatic --noinput on my remote server which does provide further insight:

› heroku ps:exec -a <project-name>
 ›   Warning: heroku update available from 7.67.2 to 7.68.2.
Establishing credentials... done
Connecting to web.1 on ⬢ <project-name>.. 
(failed reverse-i-search)`': ^C
~ $ python manage.py collectstatic --noinput
Traceback (most recent call last):
  File "/app/manage.py", line 22, in <module>
    main()
  File "/app/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/app/.heroku/python/lib/python3.11/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/app/.heroku/python/lib/python3.11/site-packages/django/core/management/__init__.py", line 386, in execute
    settings.INSTALLED_APPS
  File "/app/.heroku/python/lib/python3.11/site-packages/django/conf/__init__.py", line 92, in __getattr__
    self._setup(name)
  File "/app/.heroku/python/lib/python3.11/site-packages/django/conf/__init__.py", line 79, in _setup
    self._wrapped = Settings(settings_module)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.11/site-packages/django/conf/__init__.py", line 190, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/app/<project-name>/settings.py", line 27, in <module>
    SECRET_KEY = config('SECRET_KEY')
                 ^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.11/site-packages/decouple.py", line 248, in __call__
    return self.config(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.11/site-packages/decouple.py", line 107, in __call__
    return self.get(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.heroku/python/lib/python3.11/site-packages/decouple.py", line 92, in get
    raise UndefinedValueError('{} not found. Declare it as envvar or define a default value.'.format(option))
decouple.UndefinedValueError: SECRET_KEY not found. Declare it as envvar or define a default value.

As you can see it is referring to line 27 with a SECRET_KEY using decouple’s config function but I have assuredly commented that out in my latest settings.py as described originally above. So I am not sure why Heroku is not looking at the most recent version in my latest commit.

Any idea what could be going on?

I’m back. With some new insight. But still not a resolution.

Heroku is rejecting my push because the pre-receive hook fails. The SECRET_KEY error is indirectly related. Heroku isn’t landing any changes (since several commits back) because it just never gets there. With Heroku, pre-receive hooks are like a ‘gate’ for receiving pushes: if the hook fails, then the session ends and the push doesn’t land.

In my long traceback quoted initially, this is the tell:

remote:        whitenoise.storage.MissingFileError: The file 'vendor/bootswatch/default/bootstrap.min.css.map' could not be found with <whitenoise.storage.CompressedManifestStaticFilesStorage object at 0x7f0bf2f350c0>.
remote:        The CSS file 'vendor/bootswatch/default/bootstrap.min.css' references a file which could not be found:
remote:          vendor/bootswatch/default/bootstrap.min.css.map
remote:        Please check the URL references in this CSS file, particularly any
remote:        relative paths which might be pointing to the wrong location.

It can’t find: vendor/bootswatch/default/bootstrap.min.css.map. It appears Heroku is getting thrown off by the fact that this file that ends with a strange .map extension - - it simply doesn’t exist. That’s the problem I am trying to resolve now.

A bit of background here: I’m working with a new Admin Dashboard theme replacement tool called jazzmin. It’s really easy to install and now the Admin Dashboard looks fantastic (locally). In my source code, there is no instance of vendor or bootswatch. It’s not in either of my static folders and there is no jazzmin web app directory either.

So I found the jazzmin source code on GitHub and located the vendor bootswatch css file! Here it is on the master branch:

At that location, if you click the latest commit (dated as recently as January 26), all the way at the bottom of the file the relevant line is commented out which references the bootstrap css file location in the source. The commented out line reads:

/*# sourceMappingURL=bootstrap.min.css.map */

That’s a reflection of the issue I have documented above. It appears other people had a similar issue but it should be resolved in my case because I am using the latest version. That’s all the insight I’ve got. Not sure what to try or where to turn to next.

Dear @KenWhitesell, where were you, my friend? You’re usually my wingman! I suppose my issue is too specific to Heroku and my inquiry might be outside your expertise? But based on this ‘lead’ I’ve reached above, is there anything you (Ken or anyone else) can add or suggest I look out for or into next?

You are correct - I don’t use Heroku. I don’t know enough about it to offer advice on any issue concerning it.

So I did some CSS changes on my local, ran git add ., git commit -am "Hello",git push heroku master, and for some reason two commmits ago, things stopped getting updated.

It commits fine, and doesn’t show any input out of the ordinary.

I tried making a new branch and pushing it to the heroku branch, but still nada. What gives.?