Constructing Dependencies from a Pillar in Saltstack
This templated SLS file works splendidly:

{% if 'components' in salt.pillar.items() %}

include:
{% for component in salt.pillar.get('components').keys() %}
  - {{ component }}
{% endfor %}

{% endif %}


However, it requires changing my pillar key structure. From the original question, you see the structure as:

my-minion-id:
    ----------
    components:
        - a-dependency-name


Instead, it needs to be:

my-minion-id:
    ----------
    components:
        ----------
        a-dependency-name:
            None


Note that a-dependency-name is now a dict, and has a single key/value, None. Thus the pillar SLS file needs to change from

components:
  - a-dependency-name


to

components:
  a-dependency-name: ~


While you can get away with not using no-value dictionaries (and thus get rid of the .keys() in the template) and use lists instead, if you do that, you can't merge the components from multiple different pillars; each pillar Salt applies will override the components key from the previous, and the last pillar read will win. If you want to merge pillars (we are talking about role-based assignment, here), this would appear to be the necessary construct.

With that, the output of salt my-minion-id state.show_sls components is then correct:

$ salt my-minion-id state.show_sls components
my-minion-id:
    ----------
    a-dependency-name:
      ----------
      ...


pillar.items() in Jinja templates turns out not to be quite equivalent to salt.pillar.items(); if you try using pillar.ls(), for example, you may see the following error:

Rendering SLS 'base:components' failed: Jinja variable 'salt.pillar object' has no attribute 'ls'


Whether that means one should avoid the implicit salt. prefix shortcut Jinja provides, or instead use a construct like {% if pillar['components'] is defined %} (thanks, @brousch, for the advice), I can't say.