It’s triggered in wp_publish_post()
that calls:
wp_transition_post_status( 'publish', $old_status, $post );
that fires up action calls, dynamically with:
do_action( "{$new_status}_{$post->post_type}", $post->ID, $post );
where "{$new_status}_{$post->post_type}"
becomes "publish_post"
in your case.