Where is publish_post hook fired?

As @shanebp suggested you in a comment to OP, that is one of the hook fired by the function wp_transition_post_status, it’s a bit hard to find it doing a search in code because is a dynamic hook, in facts the line in code that fires it looks like:

do_action( "{$new_status}_{$post->post_type}", $post->ID, $post );

Where $new_status is the new status a post has after un update and $post->post_type is, as you can guess, the post type.

So the form "publish_post" is only one of possible hooks, fired when a post of standard post type has been published, to make an example same line in code will also fire "trash_page" when you delete a page, and so on.

As you can see in the source it is the last of status transition hooks being fired.

For the others and also for additional info look at Post Status Transitions page in Codex.

If you mind have a look, the function wp_transition_post_status is called inside the wp_insert_post function, in current version at line #3431 of wp-includes/post.php.

There you can see

if ( 'attachment' !== $postarr['post_type'] ) {
  wp_transition_post_status( $data['post_status'], $previous_status, $post );
}

making clear that function and related hooks aren’t called for 'attachment' post type.